diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.c b/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.c new file mode 100644 index 0000000..7a68306 --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.c @@ -0,0 +1,339 @@ +/* + * 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 "ace.h" +#include "internal-sliscp-light.h" +#include "internal-util.h" +#include + +/** + * \brief Size of the state for the internal ACE permutation. + */ +#define ACE_STATE_SIZE SLISCP_LIGHT320_STATE_SIZE + +/** + * \brief Rate for absorbing data into the ACE state and for + * squeezing data out again. + */ +#define ACE_RATE 8 + +aead_cipher_t const ace_cipher = { + "ACE", + ACE_KEY_SIZE, + ACE_NONCE_SIZE, + ACE_TAG_SIZE, + AEAD_FLAG_NONE, + ace_aead_encrypt, + ace_aead_decrypt +}; + +aead_hash_algorithm_t const ace_hash_algorithm = { + "ACE-HASH", + sizeof(ace_hash_state_t), + ACE_HASH_SIZE, + AEAD_FLAG_NONE, + ace_hash, + (aead_hash_init_t)ace_hash_init, + (aead_hash_update_t)ace_hash_update, + (aead_hash_finalize_t)ace_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +/* Indices of where a rate byte is located in the state. We don't + * need this array any more because sliscp_light320_permute() operates + * on byte-swapped states where the rate bytes are contiguous in the + * first 8 bytes */ +/* +static unsigned char const ace_rate_posn[8] = { + 0, 1, 2, 3, 16, 17, 18, 19 +}; +*/ + +/** + * \brief Initializes the ACE state. + * + * \param state ACE permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void ace_init + (unsigned char state[ACE_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by interleaving the key and nonce */ + memcpy(state, k, 8); + memcpy(state + 8, npub, 8); + memcpy(state + 16, k + 8, 8); + memset(state + 24, 0, 8); + memcpy(state + 32, npub + 8, 8); + + /* Swap some of the state bytes to make the rate bytes contiguous */ + sliscp_light320_swap(state); + + /* Run the permutation to scramble the initial state */ + sliscp_light320_permute(state); + + /* Absorb the key in two further permutation operations */ + lw_xor_block(state, k, 8); + sliscp_light320_permute(state); + lw_xor_block(state, k + 8, 8); + sliscp_light320_permute(state); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= ACE_RATE) { + lw_xor_block(state, ad, ACE_RATE); + state[ACE_STATE_SIZE - 1] ^= 0x01; /* domain separation */ + sliscp_light320_permute(state); + ad += ACE_RATE; + adlen -= ACE_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state, ad, temp); + state[temp] ^= 0x80; /* padding */ + state[ACE_STATE_SIZE - 1] ^= 0x01; /* domain separation */ + sliscp_light320_permute(state); + } +} + +/** + * \brief Finalizes the ACE encryption or decryption operation. + * + * \param state ACE permutation state. + * \param k Points to the 128-bit key. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void ace_finalize + (unsigned char state[ACE_STATE_SIZE], const unsigned char *k, + unsigned char *tag) +{ + /* Absorb the key into the state again */ + lw_xor_block(state, k, 8); + sliscp_light320_permute(state); + lw_xor_block(state, k + 8, 8); + sliscp_light320_permute(state); + + /* Swap the state bytes back to the canonical order */ + sliscp_light320_swap(state); + + /* Copy out the authentication tag */ + memcpy(tag, state, 8); + memcpy(tag + 8, state + 16, 8); +} + +int ace_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) +{ + unsigned char state[ACE_STATE_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ACE_TAG_SIZE; + + /* Initialize the ACE state and absorb the associated data */ + ace_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= ACE_RATE) { + lw_xor_block_2_dest(c, state, m, ACE_RATE); + state[ACE_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light320_permute(state); + c += ACE_RATE; + m += ACE_RATE; + mlen -= ACE_RATE; + } + temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state, m, temp); + state[temp] ^= 0x80; /* padding */ + state[ACE_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light320_permute(state); + c += mlen; + + /* Generate the authentication tag */ + ace_finalize(state, k, c); + return 0; +} + +int ace_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) +{ + unsigned char state[ACE_STATE_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ACE_TAG_SIZE) + return -1; + *mlen = clen - ACE_TAG_SIZE; + + /* Initialize the ACE state and absorb the associated data */ + ace_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ACE_TAG_SIZE; + while (clen >= ACE_RATE) { + lw_xor_block_swap(m, state, c, ACE_RATE); + state[ACE_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light320_permute(state); + c += ACE_RATE; + m += ACE_RATE; + clen -= ACE_RATE; + } + temp = (unsigned)clen; + lw_xor_block_swap(m, state, c, temp); + state[temp] ^= 0x80; /* padding */ + state[ACE_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light320_permute(state); + c += clen; + + /* Finalize the ACE state and compare against the authentication tag */ + ace_finalize(state, k, state); + return aead_check_tag(mtemp, *mlen, state, c, ACE_TAG_SIZE); +} + +/* Pre-hashed version of the ACE-HASH initialization vector */ +static unsigned char const ace_hash_iv[ACE_STATE_SIZE] = { + 0xb9, 0x7d, 0xda, 0x3f, 0x66, 0x2c, 0xd1, 0xa6, + 0x65, 0xd1, 0x80, 0xd6, 0x49, 0xdc, 0xa1, 0x8c, + 0x0c, 0x5f, 0x0e, 0xca, 0x70, 0x37, 0x58, 0x75, + 0x29, 0x7d, 0xb0, 0xb0, 0x72, 0x73, 0xce, 0xa8, + 0x99, 0x71, 0xde, 0x8a, 0x9a, 0x65, 0x72, 0x24 +}; + +int ace_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char state[ACE_STATE_SIZE]; + unsigned temp; + + /* Load the initialization vector and hash it, which can be pre-computed */ + /* + memset(state, 0, sizeof(state)); + state[8] = 0x80; + state[9] = 0x40; + state[10] = 0x40; + sliscp_light320_swap(state); + sliscp_light320_permute(state); + */ + memcpy(state, ace_hash_iv, ACE_STATE_SIZE); + + /* Absorb the input data */ + while (inlen >= ACE_RATE) { + lw_xor_block(state, in, ACE_RATE); + sliscp_light320_permute(state); + in += ACE_RATE; + inlen -= ACE_RATE; + } + temp = (unsigned)inlen; + lw_xor_block(state, in, temp); + state[temp] ^= 0x80; /* padding */ + sliscp_light320_permute(state); + + /* Squeeze out the hash value */ + memcpy(out, state, 8); + for (temp = 0; temp < 3; ++temp) { + out += 8; + sliscp_light320_permute(state); + memcpy(out, state, 8); + } + return 0; +} + +void ace_hash_init(ace_hash_state_t *state) +{ + memcpy(state->s.state, ace_hash_iv, ACE_STATE_SIZE); + state->s.count = 0; +} + +void ace_hash_update + (ace_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + unsigned len; + + /* Handle the left-over rate block from last time */ + if (state->s.count != 0) { + len = ACE_RATE - state->s.count; + if (len > inlen) + len = (unsigned)inlen; + lw_xor_block(state->s.state + state->s.count, in, len); + in += len; + inlen -= len; + state->s.count += len; + if (state->s.count >= ACE_RATE) { + sliscp_light320_permute(state->s.state); + state->s.count = 0; + } else { + /* Not enough input data yet to fill up the whole block */ + return; + } + } + + /* Process as many full rate blocks as we can */ + while (inlen >= ACE_RATE) { + lw_xor_block(state->s.state, in, ACE_RATE); + sliscp_light320_permute(state->s.state); + in += ACE_RATE; + inlen -= ACE_RATE; + } + + /* Handle any left-over data */ + len = (unsigned)inlen; + lw_xor_block(state->s.state, in, len); + state->s.count = len; +} + +void ace_hash_finalize(ace_hash_state_t *state, unsigned char *out) +{ + unsigned temp; + + /* Pad and hash the final input block */ + state->s.state[state->s.count] ^= 0x80; + sliscp_light320_permute(state->s.state); + state->s.count = 0; + + /* Squeeze out the hash value */ + memcpy(out, state->s.state, 9); + for (temp = 0; temp < 3; ++temp) { + out += 8; + sliscp_light320_permute(state->s.state); + memcpy(out, state->s.state, 8); + } +} diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.h b/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.h new file mode 100644 index 0000000..4497927 --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/ace.h @@ -0,0 +1,197 @@ +/* + * 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_ACE_H +#define LWCRYPTO_ACE_H + +#include "aead-common.h" + +/** + * \file ace.h + * \brief ACE authenticated encryption algorithm. + * + * ACE is an authenticated encryption algorithm with a 128-bit key, + * a 128-bit nonce, and a 128-bit tag. It uses a duplex construction + * on top of a 320-bit permutation. The permutation is a generalised + * version of sLiSCP-light, extended from 256 bits to 320 bits. + * ACE also has a companion hash algorithm with a 256-bit output. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/ace + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ACE. + */ +#define ACE_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for ACE. + */ +#define ACE_TAG_SIZE 16 + +/** + * \brief Size of the nonce for ACE. + */ +#define ACE_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for ACE-HASH. + */ +#define ACE_HASH_SIZE 32 + +/** + * \brief Meta-information block for the ACE cipher. + */ +extern aead_cipher_t const ace_cipher; + +/** + * \brief Meta-information block for the ACE-HASH hash algorithm. + */ +extern aead_hash_algorithm_t const ace_hash_algorithm; + +/** + * \brief State information for the ACE-HASH incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[40]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} ace_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with ACE. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ace_aead_decrypt() + */ +int ace_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); + +/** + * \brief Decrypts and authenticates a packet with ACE. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ace_aead_encrypt() + */ +int ace_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); + +/** + * \brief Hashes a block of input data with ACE-HASH to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ACE_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 ace_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ACE-HASH hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ace_hash_update(), ace_hash_finalize(), ace_hash() + */ +void ace_hash_init(ace_hash_state_t *state); + +/** + * \brief Updates the ACE-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. + * + * \sa ace_hash_init(), ace_hash_finalize() + */ +void ace_hash_update + (ace_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an ACE-HASH hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa ace_hash_init(), ace_hash_update() + */ +void ace_hash_finalize(ace_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.c b/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.h b/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/api.h b/ace/Implementations/crypto_aead/aceae128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/encrypt.c b/ace/Implementations/crypto_aead/aceae128v1/rhys/encrypt.c new file mode 100644 index 0000000..99cb7f3 --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "ace.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 ace_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 ace_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.c b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.c new file mode 100644 index 0000000..69b4519 --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.c @@ -0,0 +1,408 @@ +/* + * 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 "internal-sliscp-light.h" + +/** + * \brief Performs one round of the Simeck-64 block cipher. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + */ +#define simeck64_round(x, y) \ + do { \ + (y) ^= (leftRotate5((x)) & (x)) ^ leftRotate1((x)) ^ \ + 0xFFFFFFFEU ^ (_rc & 1); \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 64-bit block with the 8 round version of Simeck-64. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck64_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck64_round(x, y); /* Round 1 */ \ + simeck64_round(y, x); /* Round 2 */ \ + simeck64_round(x, y); /* Round 3 */ \ + simeck64_round(y, x); /* Round 4 */ \ + simeck64_round(x, y); /* Round 5 */ \ + simeck64_round(y, x); /* Round 6 */ \ + simeck64_round(x, y); /* Round 7 */ \ + simeck64_round(y, x); /* Round 8 */ \ + } while (0) + +/* Helper macros for 48-bit left rotations */ +#define leftRotate5_48(x) (((x) << 5) | ((x) >> 19)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 23)) + +/** + * \brief Performs one round of the Simeck-48 block cipher. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + */ +#define simeck48_round(x, y) \ + do { \ + (y) ^= (leftRotate5_48((x)) & (x)) ^ leftRotate1_48((x)) ^ \ + 0x00FFFFFEU ^ (_rc & 1); \ + (y) &= 0x00FFFFFFU; \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 48-bit block with the 6 round version of Simeck-48. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck48_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck48_round(x, y); /* Round 1 */ \ + simeck48_round(y, x); /* Round 2 */ \ + simeck48_round(x, y); /* Round 3 */ \ + simeck48_round(y, x); /* Round 4 */ \ + simeck48_round(x, y); /* Round 5 */ \ + simeck48_round(y, x); /* Round 6 */ \ + } while (0) + +/* Interleaved rc0, rc1, sc0, and sc1 values for each round */ +static unsigned char const sliscp_light256_RC[18 * 4] = { + 0x0f, 0x47, 0x08, 0x64, 0x04, 0xb2, 0x86, 0x6b, + 0x43, 0xb5, 0xe2, 0x6f, 0xf1, 0x37, 0x89, 0x2c, + 0x44, 0x96, 0xe6, 0xdd, 0x73, 0xee, 0xca, 0x99, + 0xe5, 0x4c, 0x17, 0xea, 0x0b, 0xf5, 0x8e, 0x0f, + 0x47, 0x07, 0x64, 0x04, 0xb2, 0x82, 0x6b, 0x43, + 0xb5, 0xa1, 0x6f, 0xf1, 0x37, 0x78, 0x2c, 0x44, + 0x96, 0xa2, 0xdd, 0x73, 0xee, 0xb9, 0x99, 0xe5, + 0x4c, 0xf2, 0xea, 0x0b, 0xf5, 0x85, 0x0f, 0x47, + 0x07, 0x23, 0x04, 0xb2, 0x82, 0xd9, 0x43, 0xb5 +}; + +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 24); /* Assumes the block is pre-swapped */ + x4 = be_load_word32(block + 16); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 12); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 8, x2); + be_store_word32(block + 24, x3); /* Assumes the block is pre-swapped */ + be_store_word32(block + 16, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 12, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spix(unsigned char block[32]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 12); + t2 = le_load_word32(block + 24); + le_store_word32(block + 24, t1); + le_store_word32(block + 12, t2); +} + +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x3 = be_load_word32(block + 20); + x4 = be_load_word32(block + 8); + x5 = be_load_word32(block + 12); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 16, x2); /* Assumes the block is pre-swapped */ + be_store_word32(block + 20, x3); + be_store_word32(block + 8, x4); + be_store_word32(block + 12, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spoc(unsigned char block[32]) +{ + uint64_t t1, t2; + t1 = le_load_word64(block + 8); + t2 = le_load_word64(block + 16); + le_store_word64(block + 16, t1); + le_store_word64(block + 8, t2); +} + +/* Load a big-endian 24-bit word from a byte buffer */ +#define be_load_word24(ptr) \ + ((((uint32_t)((ptr)[0])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[2]))) + +/* Store a big-endian 24-bit word into a byte buffer */ +#define be_store_word24(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 16); \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)_x; \ + } while (0) + +void sliscp_light192_permute(unsigned char block[24]) +{ + /* Interleaved rc0, rc1, sc0, and sc1 values for each round */ + static unsigned char const RC[18 * 4] = { + 0x07, 0x27, 0x08, 0x29, 0x04, 0x34, 0x0c, 0x1d, + 0x06, 0x2e, 0x0a, 0x33, 0x25, 0x19, 0x2f, 0x2a, + 0x17, 0x35, 0x38, 0x1f, 0x1c, 0x0f, 0x24, 0x10, + 0x12, 0x08, 0x36, 0x18, 0x3b, 0x0c, 0x0d, 0x14, + 0x26, 0x0a, 0x2b, 0x1e, 0x15, 0x2f, 0x3e, 0x31, + 0x3f, 0x38, 0x01, 0x09, 0x20, 0x24, 0x21, 0x2d, + 0x30, 0x36, 0x11, 0x1b, 0x28, 0x0d, 0x39, 0x16, + 0x3c, 0x2b, 0x05, 0x3d, 0x22, 0x3e, 0x27, 0x03, + 0x13, 0x01, 0x34, 0x02, 0x1a, 0x21, 0x2e, 0x23 + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables. Each 24-bit block is + * placed into a separate 32-bit word which improves efficiency below */ + x0 = be_load_word24(block); + x1 = be_load_word24(block + 3); + x2 = be_load_word24(block + 6); + x3 = be_load_word24(block + 9); + x4 = be_load_word24(block + 12); + x5 = be_load_word24(block + 15); + x6 = be_load_word24(block + 18); + x7 = be_load_word24(block + 21); + + /* Perform all permutation rounds */ + for (round = 0; round < 18; ++round, rc += 4) { + /* Apply Simeck-48 to two of the 48-bit sub-blocks */ + simeck48_box(x2, x3, rc[0]); + simeck48_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0x00FFFFFFU; + x1 ^= 0x00FFFF00U ^ rc[2]; + x4 ^= 0x00FFFFFFU; + x5 ^= 0x00FFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word24(block, x0); + be_store_word24(block + 3, x1); + be_store_word24(block + 6, x2); + be_store_word24(block + 9, x3); + be_store_word24(block + 12, x4); + be_store_word24(block + 15, x5); + be_store_word24(block + 18, x6); + be_store_word24(block + 21, x7); +} + +void sliscp_light320_permute(unsigned char block[40]) +{ + /* Interleaved rc0, rc1, rc2, sc0, sc1, and sc2 values for each round */ + static unsigned char const RC[16 * 6] = { + 0x07, 0x53, 0x43, 0x50, 0x28, 0x14, 0x0a, 0x5d, + 0xe4, 0x5c, 0xae, 0x57, 0x9b, 0x49, 0x5e, 0x91, + 0x48, 0x24, 0xe0, 0x7f, 0xcc, 0x8d, 0xc6, 0x63, + 0xd1, 0xbe, 0x32, 0x53, 0xa9, 0x54, 0x1a, 0x1d, + 0x4e, 0x60, 0x30, 0x18, 0x22, 0x28, 0x75, 0x68, + 0x34, 0x9a, 0xf7, 0x6c, 0x25, 0xe1, 0x70, 0x38, + 0x62, 0x82, 0xfd, 0xf6, 0x7b, 0xbd, 0x96, 0x47, + 0xf9, 0x9d, 0xce, 0x67, 0x71, 0x6b, 0x76, 0x40, + 0x20, 0x10, 0xaa, 0x88, 0xa0, 0x4f, 0x27, 0x13, + 0x2b, 0xdc, 0xb0, 0xbe, 0x5f, 0x2f, 0xe9, 0x8b, + 0x09, 0x5b, 0xad, 0xd6, 0xcf, 0x59, 0x1e, 0xe9, + 0x74, 0xba, 0xb7, 0xc6, 0xad, 0x7f, 0x3f, 0x1f + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 12); + x4 = be_load_word32(block + 4); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + x8 = be_load_word32(block + 32); + x9 = be_load_word32(block + 36); + + /* Perform all permutation rounds */ + for (round = 0; round < 16; ++round, rc += 6) { + /* Apply Simeck-64 to three of the 64-bit sub-blocks */ + simeck64_box(x0, x1, rc[0]); + simeck64_box(x4, x5, rc[1]); + simeck64_box(x8, x9, rc[2]); + x6 ^= x8; + x7 ^= x9; + x2 ^= x4; + x3 ^= x5; + x8 ^= x0; + x9 ^= x1; + + /* Add step constants */ + x2 ^= 0xFFFFFFFFU; + x3 ^= 0xFFFFFF00U ^ rc[3]; + x6 ^= 0xFFFFFFFFU; + x7 ^= 0xFFFFFF00U ^ rc[4]; + x8 ^= 0xFFFFFFFFU; + x9 ^= 0xFFFFFF00U ^ rc[5]; + + /* Rotate the sub-blocks */ + t0 = x8; + t1 = x9; + x8 = x2; + x9 = x3; + x2 = x4; + x3 = x5; + x4 = x0; + x5 = x1; + x0 = x6; + x1 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 16, x1); /* Assumes the block is pre-swapped */ + be_store_word32(block + 8, x2); + be_store_word32(block + 12, x3); + be_store_word32(block + 4, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); + be_store_word32(block + 32, x8); + be_store_word32(block + 36, x9); +} + +void sliscp_light320_swap(unsigned char block[40]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 4); + t2 = le_load_word32(block + 16); + le_store_word32(block + 16, t1); + le_store_word32(block + 4, t2); +} diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.h b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.h new file mode 100644 index 0000000..fa6b9ba --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-sliscp-light.h @@ -0,0 +1,169 @@ +/* + * 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_SLISCP_LIGHT_H +#define LW_INTERNAL_SLISCP_LIGHT_H + +/** + * \file internal-sliscp-light.h + * \brief sLiSCP-light permutation + * + * There are three variants of sLiSCP-light in use in the NIST submissions: + * + * \li sLiSCP-light-256 with a 256-bit block size, used in SPIX and SpoC. + * \li sLiSCP-light-192 with a 192-bit block size, used in SpoC. + * \li sLiSCP-light-320 with a 320-bit block size, used in ACE. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/ace, + * https://uwaterloo.ca/communications-security-lab/lwc/spix, + * https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for sLiSCP-light-256. + */ +#define SLISCP_LIGHT256_STATE_SIZE 32 + +/** + * \brief Size of the state for sLiSCP-light-192. + */ +#define SLISCP_LIGHT192_STATE_SIZE 24 + +/** + * \brief Size of the state for sLiSCP-light-320. + */ +#define SLISCP_LIGHT320_STATE_SIZE 40 + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SPIX cipher. SPIX places the rate bytes at + * positions 8, 9, 10, 11, 24, 25, 26, and 27. + * + * This function assumes that bytes 24-27 have been pre-swapped with + * bytes 12-15 so that the rate portion of the state is contiguous. + * + * The sliscp_light256_swap_spix() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spix() + */ +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SPIX. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spix() + */ +void sliscp_light256_swap_spix(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SpoC-128 cipher. SpoC-128 interleaves the + * rate bytes and the mask bytes. This version assumes that the + * rate and mask are in contiguous bytes of the state. + * + * SpoC-128 absorbs bytes using the mask bytes of the state at offsets + * 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, and 31. + * It squeezes bytes using the rate bytes of the state at offsets + * 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, and 23. + * + * This function assumes that bytes 8-15 have been pre-swapped with 16-23 + * so that the rate and mask portions of the state are contiguous. + * + * The sliscp_light256_swap_spoc() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spoc() + */ +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SpoC-128. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spoc() + */ +void sliscp_light256_swap_spoc(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 192-bit block. + * + * \param block Points to the block to be permuted. + */ +void sliscp_light192_permute(unsigned char block[24]); + +/** + * \brief Performs the sLiSCP-light permutation on a 320-bit block. + * + * \param block Points to the block to be permuted. + * + * The ACE specification refers to this permutation as "ACE" but that + * can be confused with the name of the AEAD mode so we call this + * permutation "sLiSCP-light-320" instead. + * + * ACE absorbs and squeezes data at the rate bytes 0, 1, 2, 3, 16, 17, 18, 19. + * Efficiency can suffer because of the discontinuity in rate byte positions. + * + * To counteract this, we assume that the input to the permutation has been + * pre-swapped: bytes 4, 5, 6, 7 are swapped with bytes 16, 17, 18, 19 so + * that the rate is contiguous at the start of the state. + * + * The sliscp_light320_swap() function can be used to switch between the + * canonical order and the pre-swapped order. + * + * \sa sliscp_light320_swap() + */ +void sliscp_light320_permute(unsigned char block[40]); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 320-bit block. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light320_permute() + */ +void sliscp_light320_swap(unsigned char block[40]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-util.h b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/ace/Implementations/crypto_aead/aceae128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.c b/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.h b/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/api.h b/ascon/Implementations/crypto_aead/ascon128av12/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.c b/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.c new file mode 100644 index 0000000..80b2e46 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.c @@ -0,0 +1,383 @@ +/* + * 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 "ascon128.h" +#include "internal-ascon.h" +#include + +/** + * \brief Initialization vector for ASCON-128. + */ +#define ASCON128_IV 0x80400c0600000000ULL + +/** + * \brief Initialization vector for ASCON-128a. + */ +#define ASCON128a_IV 0x80800c0800000000ULL + +/** + * \brief Initialization vector for ASCON-80pq. + */ +#define ASCON80PQ_IV 0xa0400c06U + +aead_cipher_t const ascon128_cipher = { + "ASCON-128", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128_aead_encrypt, + ascon128_aead_decrypt +}; + +aead_cipher_t const ascon128a_cipher = { + "ASCON-128a", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128a_aead_encrypt, + ascon128a_aead_decrypt +}; + +aead_cipher_t const ascon80pq_cipher = { + "ASCON-80pq", + ASCON80PQ_KEY_SIZE, + ASCON80PQ_NONCE_SIZE, + ASCON80PQ_TAG_SIZE, + AEAD_FLAG_NONE, + ascon80pq_aead_encrypt, + ascon80pq_aead_decrypt +}; + +/** + * \brief Absorbs data into an ASCON state. + * + * \param state The state to absorb the data into. + * \param data Points to the data to be absorbed. + * \param len Length of the data to be absorbed. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_absorb + (ascon_state_t *state, const unsigned char *data, + unsigned long long len, uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block(state->B, data, rate); + ascon_permute(state, first_round); + data += rate; + len -= rate; + } + lw_xor_block(state->B, data, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; + ascon_permute(state, first_round); +} + +/** + * \brief Encrypts a block of data with an ASCON state. + * + * \param state The state to encrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to encrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_encrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_2_dest(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_2_dest(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +/** + * \brief Decrypts a block of data with an ASCON state. + * + * \param state The state to decrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to decrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_decrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_swap(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_swap(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 16, 4); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 16, 4); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k + 4, 16); + return 0; +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON80PQ_TAG_SIZE) + return -1; + *mlen = clen - ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k + 4, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON80PQ_TAG_SIZE); +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.h b/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.h new file mode 100644 index 0000000..fd9db13 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/ascon128.h @@ -0,0 +1,408 @@ +/* + * 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_ASCON_H +#define LWCRYPTO_ASCON_H + +#include "aead-common.h" + +/** + * \file ascon128.h + * \brief ASCON-128 encryption algorithm and related family members. + * + * The ASCON family consists of several related algorithms: + * + * \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. + * \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 128 bits. This is faster than ASCON-128 but may + * not be as secure. + * \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a + * 160-bit key instead which may be more resistant against quantum computers. + * \li ASCON-HASH with a 256-bit hash output. + * + * References: https://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ASCON-128 and ASCON-128a. + */ +#define ASCON128_KEY_SIZE 16 + +/** + * \brief Size of the nonce for ASCON-128 and ASCON-128a. + */ +#define ASCON128_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-128 and ASCON-128a. + */ +#define ASCON128_TAG_SIZE 16 + +/** + * \brief Size of the key for ASCON-80pq. + */ +#define ASCON80PQ_KEY_SIZE 20 + +/** + * \brief Size of the nonce for ASCON-80pq. + */ +#define ASCON80PQ_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-80pq. + */ +#define ASCON80PQ_TAG_SIZE 16 + +/** + * \brief Size of the hash output for ASCON-HASH. + */ +#define ASCON_HASH_SIZE 32 + +/** + * \brief State information for ASCON-HASH and ASCON-XOF incremental modes. + */ +typedef union +{ + struct { + unsigned char state[40]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} ascon_hash_state_t; + +/** + * \brief Meta-information block for the ASCON-128 cipher. + */ +extern aead_cipher_t const ascon128_cipher; + +/** + * \brief Meta-information block for the ASCON-128a cipher. + */ +extern aead_cipher_t const ascon128a_cipher; + +/** + * \brief Meta-information block for the ASCON-80pq cipher. + */ +extern aead_cipher_t const ascon80pq_cipher; + +/** + * \brief Meta-information block for the ASCON-HASH algorithm. + */ +extern aead_hash_algorithm_t const ascon_hash_algorithm; + +/** + * \brief Meta-information block for the ASCON-XOF algorithm. + */ +extern aead_hash_algorithm_t const ascon_xof_algorithm; + +/** + * \brief Encrypts and authenticates a packet with ASCON-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128_aead_decrypt() + */ +int ascon128_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128_aead_encrypt() + */ +int ascon128_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-128a. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128a_aead_decrypt() + */ +int ascon128a_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128a. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128a_aead_encrypt() + */ +int ascon128a_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-80pq. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon80pq_aead_decrypt() + */ +int ascon80pq_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-80pq. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of 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. + * + * \sa ascon80pq_aead_encrypt() + */ +int ascon80pq_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); + +/** + * \brief Hashes a block of input data with ASCON-HASH. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * \sa ascon_hash_init(), ascon_hash_absorb(), ascon_hash_squeeze() + */ +int ascon_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-HASH hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_hash_update(), ascon_hash_finalize(), ascon_hash() + */ +void ascon_hash_init(ascon_hash_state_t *state); + +/** + * \brief Updates an ASCON-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. + * + * \sa ascon_hash_init(), ascon_hash_finalize() + */ +void ascon_hash_update + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an ASCON-HASH hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa ascon_hash_init(), ascon_hash_update() + */ +void ascon_hash_finalize + (ascon_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with ASCON-XOF and generates a + * fixed-length 32 byte output. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * Use ascon_xof_squeeze() instead if you need variable-length XOF ouutput. + * + * \sa ascon_xof_init(), ascon_xof_absorb(), ascon_xof_squeeze() + */ +int ascon_xof + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-XOF hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_xof_absorb(), ascon_xof_squeeze(), ascon_xof() + */ +void ascon_xof_init(ascon_hash_state_t *state); + +/** + * \brief Aborbs more input data into an ASCON-XOF state. + * + * \param state Hash 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() + */ +void ascon_xof_absorb + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Squeezes output data from an ASCON-XOF state. + * + * \param state Hash 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. + * + * \sa ascon_xof_init(), ascon_xof_update() + */ +void ascon_xof_squeeze + (ascon_hash_state_t *state, unsigned char *out, unsigned long long outlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/encrypt.c b/ascon/Implementations/crypto_aead/ascon128av12/rhys/encrypt.c new file mode 100644 index 0000000..4f35480 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "ascon128.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 ascon128a_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 ascon128a_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.c b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.h b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-util.h b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.c b/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.h b/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/api.h b/ascon/Implementations/crypto_aead/ascon128v12/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.c b/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.c new file mode 100644 index 0000000..80b2e46 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.c @@ -0,0 +1,383 @@ +/* + * 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 "ascon128.h" +#include "internal-ascon.h" +#include + +/** + * \brief Initialization vector for ASCON-128. + */ +#define ASCON128_IV 0x80400c0600000000ULL + +/** + * \brief Initialization vector for ASCON-128a. + */ +#define ASCON128a_IV 0x80800c0800000000ULL + +/** + * \brief Initialization vector for ASCON-80pq. + */ +#define ASCON80PQ_IV 0xa0400c06U + +aead_cipher_t const ascon128_cipher = { + "ASCON-128", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128_aead_encrypt, + ascon128_aead_decrypt +}; + +aead_cipher_t const ascon128a_cipher = { + "ASCON-128a", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128a_aead_encrypt, + ascon128a_aead_decrypt +}; + +aead_cipher_t const ascon80pq_cipher = { + "ASCON-80pq", + ASCON80PQ_KEY_SIZE, + ASCON80PQ_NONCE_SIZE, + ASCON80PQ_TAG_SIZE, + AEAD_FLAG_NONE, + ascon80pq_aead_encrypt, + ascon80pq_aead_decrypt +}; + +/** + * \brief Absorbs data into an ASCON state. + * + * \param state The state to absorb the data into. + * \param data Points to the data to be absorbed. + * \param len Length of the data to be absorbed. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_absorb + (ascon_state_t *state, const unsigned char *data, + unsigned long long len, uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block(state->B, data, rate); + ascon_permute(state, first_round); + data += rate; + len -= rate; + } + lw_xor_block(state->B, data, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; + ascon_permute(state, first_round); +} + +/** + * \brief Encrypts a block of data with an ASCON state. + * + * \param state The state to encrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to encrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_encrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_2_dest(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_2_dest(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +/** + * \brief Decrypts a block of data with an ASCON state. + * + * \param state The state to decrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to decrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_decrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_swap(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_swap(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 16, 4); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 16, 4); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k + 4, 16); + return 0; +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON80PQ_TAG_SIZE) + return -1; + *mlen = clen - ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k + 4, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON80PQ_TAG_SIZE); +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.h b/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.h new file mode 100644 index 0000000..fd9db13 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/ascon128.h @@ -0,0 +1,408 @@ +/* + * 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_ASCON_H +#define LWCRYPTO_ASCON_H + +#include "aead-common.h" + +/** + * \file ascon128.h + * \brief ASCON-128 encryption algorithm and related family members. + * + * The ASCON family consists of several related algorithms: + * + * \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. + * \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 128 bits. This is faster than ASCON-128 but may + * not be as secure. + * \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a + * 160-bit key instead which may be more resistant against quantum computers. + * \li ASCON-HASH with a 256-bit hash output. + * + * References: https://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ASCON-128 and ASCON-128a. + */ +#define ASCON128_KEY_SIZE 16 + +/** + * \brief Size of the nonce for ASCON-128 and ASCON-128a. + */ +#define ASCON128_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-128 and ASCON-128a. + */ +#define ASCON128_TAG_SIZE 16 + +/** + * \brief Size of the key for ASCON-80pq. + */ +#define ASCON80PQ_KEY_SIZE 20 + +/** + * \brief Size of the nonce for ASCON-80pq. + */ +#define ASCON80PQ_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-80pq. + */ +#define ASCON80PQ_TAG_SIZE 16 + +/** + * \brief Size of the hash output for ASCON-HASH. + */ +#define ASCON_HASH_SIZE 32 + +/** + * \brief State information for ASCON-HASH and ASCON-XOF incremental modes. + */ +typedef union +{ + struct { + unsigned char state[40]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} ascon_hash_state_t; + +/** + * \brief Meta-information block for the ASCON-128 cipher. + */ +extern aead_cipher_t const ascon128_cipher; + +/** + * \brief Meta-information block for the ASCON-128a cipher. + */ +extern aead_cipher_t const ascon128a_cipher; + +/** + * \brief Meta-information block for the ASCON-80pq cipher. + */ +extern aead_cipher_t const ascon80pq_cipher; + +/** + * \brief Meta-information block for the ASCON-HASH algorithm. + */ +extern aead_hash_algorithm_t const ascon_hash_algorithm; + +/** + * \brief Meta-information block for the ASCON-XOF algorithm. + */ +extern aead_hash_algorithm_t const ascon_xof_algorithm; + +/** + * \brief Encrypts and authenticates a packet with ASCON-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128_aead_decrypt() + */ +int ascon128_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128_aead_encrypt() + */ +int ascon128_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-128a. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128a_aead_decrypt() + */ +int ascon128a_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128a. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128a_aead_encrypt() + */ +int ascon128a_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-80pq. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon80pq_aead_decrypt() + */ +int ascon80pq_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-80pq. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of 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. + * + * \sa ascon80pq_aead_encrypt() + */ +int ascon80pq_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); + +/** + * \brief Hashes a block of input data with ASCON-HASH. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * \sa ascon_hash_init(), ascon_hash_absorb(), ascon_hash_squeeze() + */ +int ascon_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-HASH hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_hash_update(), ascon_hash_finalize(), ascon_hash() + */ +void ascon_hash_init(ascon_hash_state_t *state); + +/** + * \brief Updates an ASCON-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. + * + * \sa ascon_hash_init(), ascon_hash_finalize() + */ +void ascon_hash_update + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an ASCON-HASH hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa ascon_hash_init(), ascon_hash_update() + */ +void ascon_hash_finalize + (ascon_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with ASCON-XOF and generates a + * fixed-length 32 byte output. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * Use ascon_xof_squeeze() instead if you need variable-length XOF ouutput. + * + * \sa ascon_xof_init(), ascon_xof_absorb(), ascon_xof_squeeze() + */ +int ascon_xof + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-XOF hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_xof_absorb(), ascon_xof_squeeze(), ascon_xof() + */ +void ascon_xof_init(ascon_hash_state_t *state); + +/** + * \brief Aborbs more input data into an ASCON-XOF state. + * + * \param state Hash 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() + */ +void ascon_xof_absorb + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Squeezes output data from an ASCON-XOF state. + * + * \param state Hash 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. + * + * \sa ascon_xof_init(), ascon_xof_update() + */ +void ascon_xof_squeeze + (ascon_hash_state_t *state, unsigned char *out, unsigned long long outlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/encrypt.c b/ascon/Implementations/crypto_aead/ascon128v12/rhys/encrypt.c new file mode 100644 index 0000000..f32284a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "ascon128.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 ascon128_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 ascon128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.c b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.h b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-util.h b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.c b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.h b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/api.h b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/api.h new file mode 100644 index 0000000..f99b349 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 20 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.c b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.c new file mode 100644 index 0000000..80b2e46 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.c @@ -0,0 +1,383 @@ +/* + * 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 "ascon128.h" +#include "internal-ascon.h" +#include + +/** + * \brief Initialization vector for ASCON-128. + */ +#define ASCON128_IV 0x80400c0600000000ULL + +/** + * \brief Initialization vector for ASCON-128a. + */ +#define ASCON128a_IV 0x80800c0800000000ULL + +/** + * \brief Initialization vector for ASCON-80pq. + */ +#define ASCON80PQ_IV 0xa0400c06U + +aead_cipher_t const ascon128_cipher = { + "ASCON-128", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128_aead_encrypt, + ascon128_aead_decrypt +}; + +aead_cipher_t const ascon128a_cipher = { + "ASCON-128a", + ASCON128_KEY_SIZE, + ASCON128_NONCE_SIZE, + ASCON128_TAG_SIZE, + AEAD_FLAG_NONE, + ascon128a_aead_encrypt, + ascon128a_aead_decrypt +}; + +aead_cipher_t const ascon80pq_cipher = { + "ASCON-80pq", + ASCON80PQ_KEY_SIZE, + ASCON80PQ_NONCE_SIZE, + ASCON80PQ_TAG_SIZE, + AEAD_FLAG_NONE, + ascon80pq_aead_encrypt, + ascon80pq_aead_decrypt +}; + +/** + * \brief Absorbs data into an ASCON state. + * + * \param state The state to absorb the data into. + * \param data Points to the data to be absorbed. + * \param len Length of the data to be absorbed. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_absorb + (ascon_state_t *state, const unsigned char *data, + unsigned long long len, uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block(state->B, data, rate); + ascon_permute(state, first_round); + data += rate; + len -= rate; + } + lw_xor_block(state->B, data, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; + ascon_permute(state, first_round); +} + +/** + * \brief Encrypts a block of data with an ASCON state. + * + * \param state The state to encrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to encrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_encrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_2_dest(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_2_dest(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +/** + * \brief Decrypts a block of data with an ASCON state. + * + * \param state The state to decrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to decrypt from \a src into \a dest. + * \param rate Block rate, which is either 8 or 16. + * \param first_round First round of the permutation to apply each block. + */ +static void ascon_decrypt + (ascon_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len, + uint8_t rate, uint8_t first_round) +{ + while (len >= rate) { + lw_xor_block_swap(dest, state->B, src, rate); + ascon_permute(state, first_round); + dest += rate; + src += rate; + len -= rate; + } + lw_xor_block_swap(dest, state->B, src, (unsigned)len); + state->B[(unsigned)len] ^= 0x80; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 16, 4); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k, 16); + return 0; +} + +int ascon128a_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON128_TAG_SIZE) + return -1; + *mlen = clen - ASCON128_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word64(state.B, ASCON128a_IV); + memcpy(state.B + 8, k, ASCON128_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON128_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, ASCON128_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 16, 4); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 16, 4); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 16, k, ASCON128_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON128_TAG_SIZE); +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Encrypt the plaintext to create the ciphertext */ + ascon_encrypt(&state, c, m, mlen, 8, 6); + + /* Finalize and compute the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block_2_src(c + mlen, state.B + 24, k + 4, 16); + return 0; +} + +int ascon80pq_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) +{ + ascon_state_t state; + (void)nsec; + + /* Set the length of the returned plaintext */ + if (clen < ASCON80PQ_TAG_SIZE) + return -1; + *mlen = clen - ASCON80PQ_TAG_SIZE; + + /* Initialize the ASCON state */ + be_store_word32(state.B, ASCON80PQ_IV); + memcpy(state.B + 4, k, ASCON80PQ_KEY_SIZE); + memcpy(state.B + 24, npub, ASCON80PQ_NONCE_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 20, k, ASCON80PQ_KEY_SIZE); + + /* Absorb the associated data into the state */ + if (adlen > 0) + ascon_absorb(&state, ad, adlen, 8, 6); + + /* Separator between the associated data and the payload */ + state.B[39] ^= 0x01; + + /* Decrypt the ciphertext to create the plaintext */ + ascon_decrypt(&state, m, c, *mlen, 8, 6); + + /* Finalize and check the authentication tag */ + lw_xor_block(state.B + 8, k, ASCON80PQ_KEY_SIZE); + ascon_permute(&state, 0); + lw_xor_block(state.B + 24, k + 4, 16); + return aead_check_tag + (m, *mlen, state.B + 24, c + *mlen, ASCON80PQ_TAG_SIZE); +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.h b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.h new file mode 100644 index 0000000..fd9db13 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/ascon128.h @@ -0,0 +1,408 @@ +/* + * 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_ASCON_H +#define LWCRYPTO_ASCON_H + +#include "aead-common.h" + +/** + * \file ascon128.h + * \brief ASCON-128 encryption algorithm and related family members. + * + * The ASCON family consists of several related algorithms: + * + * \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. + * \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 128 bits. This is faster than ASCON-128 but may + * not be as secure. + * \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication + * tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a + * 160-bit key instead which may be more resistant against quantum computers. + * \li ASCON-HASH with a 256-bit hash output. + * + * References: https://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ASCON-128 and ASCON-128a. + */ +#define ASCON128_KEY_SIZE 16 + +/** + * \brief Size of the nonce for ASCON-128 and ASCON-128a. + */ +#define ASCON128_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-128 and ASCON-128a. + */ +#define ASCON128_TAG_SIZE 16 + +/** + * \brief Size of the key for ASCON-80pq. + */ +#define ASCON80PQ_KEY_SIZE 20 + +/** + * \brief Size of the nonce for ASCON-80pq. + */ +#define ASCON80PQ_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for ASCON-80pq. + */ +#define ASCON80PQ_TAG_SIZE 16 + +/** + * \brief Size of the hash output for ASCON-HASH. + */ +#define ASCON_HASH_SIZE 32 + +/** + * \brief State information for ASCON-HASH and ASCON-XOF incremental modes. + */ +typedef union +{ + struct { + unsigned char state[40]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} ascon_hash_state_t; + +/** + * \brief Meta-information block for the ASCON-128 cipher. + */ +extern aead_cipher_t const ascon128_cipher; + +/** + * \brief Meta-information block for the ASCON-128a cipher. + */ +extern aead_cipher_t const ascon128a_cipher; + +/** + * \brief Meta-information block for the ASCON-80pq cipher. + */ +extern aead_cipher_t const ascon80pq_cipher; + +/** + * \brief Meta-information block for the ASCON-HASH algorithm. + */ +extern aead_hash_algorithm_t const ascon_hash_algorithm; + +/** + * \brief Meta-information block for the ASCON-XOF algorithm. + */ +extern aead_hash_algorithm_t const ascon_xof_algorithm; + +/** + * \brief Encrypts and authenticates a packet with ASCON-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128_aead_decrypt() + */ +int ascon128_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128_aead_encrypt() + */ +int ascon128_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-128a. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon128a_aead_decrypt() + */ +int ascon128a_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-128a. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa ascon128a_aead_encrypt() + */ +int ascon128a_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); + +/** + * \brief Encrypts and authenticates a packet with ASCON-80pq. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa ascon80pq_aead_decrypt() + */ +int ascon80pq_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); + +/** + * \brief Decrypts and authenticates a packet with ASCON-80pq. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 20 bytes of 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. + * + * \sa ascon80pq_aead_encrypt() + */ +int ascon80pq_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); + +/** + * \brief Hashes a block of input data with ASCON-HASH. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * \sa ascon_hash_init(), ascon_hash_absorb(), ascon_hash_squeeze() + */ +int ascon_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-HASH hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_hash_update(), ascon_hash_finalize(), ascon_hash() + */ +void ascon_hash_init(ascon_hash_state_t *state); + +/** + * \brief Updates an ASCON-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. + * + * \sa ascon_hash_init(), ascon_hash_finalize() + */ +void ascon_hash_update + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an ASCON-HASH hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa ascon_hash_init(), ascon_hash_update() + */ +void ascon_hash_finalize + (ascon_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with ASCON-XOF and generates a + * fixed-length 32 byte output. + * + * \param out Buffer to receive the hash output which must be at least + * ASCON_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. + * + * Use ascon_xof_squeeze() instead if you need variable-length XOF ouutput. + * + * \sa ascon_xof_init(), ascon_xof_absorb(), ascon_xof_squeeze() + */ +int ascon_xof + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an ASCON-XOF hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa ascon_xof_absorb(), ascon_xof_squeeze(), ascon_xof() + */ +void ascon_xof_init(ascon_hash_state_t *state); + +/** + * \brief Aborbs more input data into an ASCON-XOF state. + * + * \param state Hash 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() + */ +void ascon_xof_absorb + (ascon_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Squeezes output data from an ASCON-XOF state. + * + * \param state Hash 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. + * + * \sa ascon_xof_init(), ascon_xof_update() + */ +void ascon_xof_squeeze + (ascon_hash_state_t *state, unsigned char *out, unsigned long long outlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/encrypt.c b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/encrypt.c new file mode 100644 index 0000000..08b7dc9 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "ascon128.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 ascon80pq_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 ascon80pq_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.c b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.h b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-util.h b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.c b/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.h b/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/api.h b/comet/Implementations/crypto_aead/comet128chamv1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.c b/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.c new file mode 100644 index 0000000..d068de2 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.c @@ -0,0 +1,607 @@ +/* + * 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 "comet.h" +#include "internal-cham.h" +#include "internal-util.h" +#include + +aead_cipher_t const comet_128_cham_cipher = { + "COMET-128_CHAM-128/128", + COMET_KEY_SIZE, + COMET_128_NONCE_SIZE, + COMET_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_128_cham_aead_encrypt, + comet_128_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_cham_cipher = { + "COMET-64_CHAM-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_cham_aead_encrypt, + comet_64_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_speck_cipher = { + "COMET-64_SPECK-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_speck_aead_encrypt, + comet_64_speck_aead_decrypt +}; + +/** + * \brief Adjusts the Z state to generate the key to use on the next block. + * + * \param Z The Z state to be adjusted. + */ +static void comet_adjust_block_key(unsigned char Z[16]) +{ + /* Doubles the 64-bit prefix to Z in the F(2^64) field */ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)(Z[7])) >> 7); + for (index = 7; index > 0; --index) + Z[index] = (Z[index] << 1) | (Z[index - 1] >> 7); + Z[0] = (Z[0] << 1) ^ (mask & 0x1B); +} + +/* Function prototype for the encrypt function of the underyling cipher */ +typedef void (*comet_encrypt_block_t) + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Processes the associated data for COMET. + * + * \param Y Internal COMET block state of \a block_size bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param block_size Size of the block for the underlying cipher. + * \param encrypt Encryption function for the underlying cipher. + * \param ad Points to the associated data. + * \param adlen Number of bytes of associated data; must be >= 1. + */ +static void comet_process_ad + (unsigned char *Y, unsigned char Z[16], unsigned block_size, + comet_encrypt_block_t encrypt, const unsigned char *ad, + unsigned long long adlen) +{ + /* Domain separator for associated data */ + Z[15] ^= 0x08; + + /* Process all associated data blocks except the last partial block */ + while (adlen >= block_size) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, block_size); + ad += block_size; + adlen -= block_size; + } + + /* Pad and process the partial block on the end */ + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + Z[15] ^= 0x10; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Shuffles the words in a 128-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_128 + (unsigned char out[16], const unsigned char in[16]) +{ + uint32_t x0, x1, x2, x3; + x0 = le_load_word32(in); + x1 = le_load_word32(in + 4); + x2 = le_load_word32(in + 8); + x3 = le_load_word32(in + 12); + le_store_word32(out, x3); + le_store_word32(out + 4, rightRotate1(x2)); + le_store_word32(out + 8, x0); + le_store_word32(out + 12, x1); +} + +/** + * \brief Shuffles the words in a 64-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_64 + (unsigned char out[8], const unsigned char in[8]) +{ + uint32_t x01 = le_load_word32(in); + uint16_t x2 = ((uint16_t)(in[4])) | (((uint16_t)(in[5])) << 8); + out[0] = in[6]; + out[1] = in[7]; + x2 = (x2 >> 1) | (x2 << 15); + out[2] = (uint8_t)x2; + out[3] = (uint8_t)(x2 >> 8); + le_store_word32(out + 4, x01); +} + +/** + * \brief Encrypts the plaintext with COMET-128 to produce the ciphertext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, 16); + lw_xor_block_2_src(c, m, Ys, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Encrypts the plaintext with COMET-64 to produce the ciphertext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, 8); + lw_xor_block_2_src(c, m, Ys, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-128 to produce the plaintext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 16); + lw_xor_block(Y, m, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-64 to produce the plaintext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 8); + lw_xor_block(Y, m, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_128(Y, Z, cham128_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_128_TAG_SIZE) + return -1; + *mlen = clen - COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_128_TAG_SIZE) + comet_decrypt_128(Y, Z, cham128_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_128_TAG_SIZE); +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, cham64_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, cham64_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} + +/** + * \brief Encrypts a 64-bit block with SPECK-64-128 in COMET byte order. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \note This version differs from standard SPECK-64 in that it uses the + * little-endian byte order from the COMET specification which is different + * from the big-endian byte order from the original SPECK paper. + */ +static void speck64_128_comet_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t l[4]; + uint32_t x, y, s; + uint8_t round; + uint8_t li_in = 0; + uint8_t li_out = 3; + + /* Unpack the key and the input block */ + s = le_load_word32(key); + l[0] = le_load_word32(key + 4); + l[1] = le_load_word32(key + 8); + l[2] = le_load_word32(key + 12); + y = le_load_word32(input); + x = le_load_word32(input + 4); + + /* Perform all encryption rounds except the last */ + for (round = 0; round < 26; ++round) { + /* Perform the round with the current key schedule word */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + + /* Calculate the next key schedule word */ + l[li_out] = (s + rightRotate8(l[li_in])) ^ round; + s = leftRotate3(s) ^ l[li_out]; + li_in = (li_in + 1) & 0x03; + li_out = (li_out + 1) & 0x03; + } + + /* Perform the last encryption round and write the result to the output */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + le_store_word32(output, y); + le_store_word32(output + 4, x); +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, speck64_128_comet_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, speck64_128_comet_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.h b/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.h new file mode 100644 index 0000000..d1b24a6 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/comet.h @@ -0,0 +1,274 @@ +/* + * 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_COMET_H +#define LWCRYPTO_COMET_H + +#include "aead-common.h" + +/** + * \file comet.h + * \brief COMET authenticated encryption algorithm. + * + * COMET is a family of authenticated encryption algorithms that are + * built around an underlying block cipher. This library implements + * three members of the family: + * + * \li COMET-128_CHAM-128/128 which has a 128-bit key, a 128-bit nonce, + * and a 128-bit tag, built around the CHAM-128/128 block cipher. + * \li COMET-64_CHAM-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the CHAM-64/128 block cipher. + * \li COMET-64_SPECK-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the SPECK-64/128 block cipher. + * + * There is also another family member that is built around AES but + * this library does not implement that version. + * + * References: https://www.isical.ac.in/~lightweight/comet/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all COMET family members. + */ +#define COMET_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for the 128-bit versions of COMET. + */ +#define COMET_128_TAG_SIZE 16 + +/** + * \brief Size of the authentication tag for the 64-bit versions of COMET. + */ +#define COMET_64_TAG_SIZE 8 + +/** + * \brief Size of the nonce for the 128-bit versions of COMET. + */ +#define COMET_128_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for the 64-bit versions of COMET. + */ +#define COMET_64_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the COMET-128_CHAM-128/128 cipher. + */ +extern aead_cipher_t const comet_128_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_CHAM-64/128 cipher. + */ +extern aead_cipher_t const comet_64_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_SPECK-64/128 cipher. + */ +extern aead_cipher_t const comet_64_speck_cipher; + +/** + * \brief Encrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_128_cham_aead_decrypt() + */ +int comet_128_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_128_cham_aead_encrypt() + */ +int comet_128_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_cham_aead_decrypt() + */ +int comet_64_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_cham_aead_encrypt() + */ +int comet_64_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_speck_aead_decrypt() + */ +int comet_64_speck_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_speck_aead_encrypt() + */ +int comet_64_speck_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/encrypt.c b/comet/Implementations/crypto_aead/comet128chamv1/rhys/encrypt.c new file mode 100644 index 0000000..66c5ad7 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "comet.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 comet_128_cham_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 comet_128_cham_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.c b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.c new file mode 100644 index 0000000..e097dbd --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.c @@ -0,0 +1,134 @@ +/* + * 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 "internal-cham.h" +#include "internal-util.h" + +void cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t x0, x1, x2, x3; + uint32_t k[8]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word32(key); + k[1] = le_load_word32(key + 4); + k[2] = le_load_word32(key + 8); + k[3] = le_load_word32(key + 12); + k[4] = k[1] ^ leftRotate1(k[1]) ^ leftRotate11(k[1]); + k[5] = k[0] ^ leftRotate1(k[0]) ^ leftRotate11(k[0]); + k[6] = k[3] ^ leftRotate1(k[3]) ^ leftRotate11(k[3]); + k[7] = k[2] ^ leftRotate1(k[2]) ^ leftRotate11(k[2]); + k[0] ^= leftRotate1(k[0]) ^ leftRotate8(k[0]); + k[1] ^= leftRotate1(k[1]) ^ leftRotate8(k[1]); + k[2] ^= leftRotate1(k[2]) ^ leftRotate8(k[2]); + k[3] ^= leftRotate1(k[3]) ^ leftRotate8(k[3]); + + /* Unpack the input block */ + x0 = le_load_word32(input); + x1 = le_load_word32(input + 4); + x2 = le_load_word32(input + 8); + x3 = le_load_word32(input + 12); + + /* Perform the 80 rounds eight at a time */ + for (round = 0; round < 80; round += 8) { + x0 = leftRotate8((x0 ^ round) + (leftRotate1(x1) ^ k[0])); + x1 = leftRotate1((x1 ^ (round + 1)) + (leftRotate8(x2) ^ k[1])); + x2 = leftRotate8((x2 ^ (round + 2)) + (leftRotate1(x3) ^ k[2])); + x3 = leftRotate1((x3 ^ (round + 3)) + (leftRotate8(x0) ^ k[3])); + x0 = leftRotate8((x0 ^ (round + 4)) + (leftRotate1(x1) ^ k[4])); + x1 = leftRotate1((x1 ^ (round + 5)) + (leftRotate8(x2) ^ k[5])); + x2 = leftRotate8((x2 ^ (round + 6)) + (leftRotate1(x3) ^ k[6])); + x3 = leftRotate1((x3 ^ (round + 7)) + (leftRotate8(x0) ^ k[7])); + } + + /* Pack the state into the output block */ + le_store_word32(output, x0); + le_store_word32(output + 4, x1); + le_store_word32(output + 8, x2); + le_store_word32(output + 12, x3); +} + +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint16_t x0, x1, x2, x3; + uint16_t k[16]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word16(key); + k[1] = le_load_word16(key + 2); + k[2] = le_load_word16(key + 4); + k[3] = le_load_word16(key + 6); + k[4] = le_load_word16(key + 8); + k[5] = le_load_word16(key + 10); + k[6] = le_load_word16(key + 12); + k[7] = le_load_word16(key + 14); + k[8] = k[1] ^ leftRotate1_16(k[1]) ^ leftRotate11_16(k[1]); + k[9] = k[0] ^ leftRotate1_16(k[0]) ^ leftRotate11_16(k[0]); + k[10] = k[3] ^ leftRotate1_16(k[3]) ^ leftRotate11_16(k[3]); + k[11] = k[2] ^ leftRotate1_16(k[2]) ^ leftRotate11_16(k[2]); + k[12] = k[5] ^ leftRotate1_16(k[5]) ^ leftRotate11_16(k[5]); + k[13] = k[4] ^ leftRotate1_16(k[4]) ^ leftRotate11_16(k[4]); + k[14] = k[7] ^ leftRotate1_16(k[7]) ^ leftRotate11_16(k[7]); + k[15] = k[6] ^ leftRotate1_16(k[6]) ^ leftRotate11_16(k[6]); + k[0] ^= leftRotate1_16(k[0]) ^ leftRotate8_16(k[0]); + k[1] ^= leftRotate1_16(k[1]) ^ leftRotate8_16(k[1]); + k[2] ^= leftRotate1_16(k[2]) ^ leftRotate8_16(k[2]); + k[3] ^= leftRotate1_16(k[3]) ^ leftRotate8_16(k[3]); + k[4] ^= leftRotate1_16(k[4]) ^ leftRotate8_16(k[4]); + k[5] ^= leftRotate1_16(k[5]) ^ leftRotate8_16(k[5]); + k[6] ^= leftRotate1_16(k[6]) ^ leftRotate8_16(k[6]); + k[7] ^= leftRotate1_16(k[7]) ^ leftRotate8_16(k[7]); + + /* Unpack the input block */ + x0 = le_load_word16(input); + x1 = le_load_word16(input + 2); + x2 = le_load_word16(input + 4); + x3 = le_load_word16(input + 6); + + /* Perform the 80 rounds four at a time */ + for (round = 0; round < 80; round += 4) { + x0 = leftRotate8_16 + ((x0 ^ round) + + (leftRotate1_16(x1) ^ k[round % 16])); + x1 = leftRotate1_16 + ((x1 ^ (round + 1)) + + (leftRotate8_16(x2) ^ k[(round + 1) % 16])); + x2 = leftRotate8_16 + ((x2 ^ (round + 2)) + + (leftRotate1_16(x3) ^ k[(round + 2) % 16])); + x3 = leftRotate1_16 + ((x3 ^ (round + 3)) + + (leftRotate8_16(x0) ^ k[(round + 3) % 16])); + } + + /* Pack the state into the output block */ + le_store_word16(output, x0); + le_store_word16(output + 2, x1); + le_store_word16(output + 4, x2); + le_store_word16(output + 6, x3); +} diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.h b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.h new file mode 100644 index 0000000..29d5ccf --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-cham.h @@ -0,0 +1,67 @@ +/* + * 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_CHAM_H +#define LW_INTERNAL_CHAM_H + +/** + * \file internal-cham.h + * \brief CHAM block cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a 128-bit block with CHAM-128-128. + * + * \param key Points to the 16 bytes of the key. + * \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 cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with CHAM-64-128. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-util.h b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/comet/Implementations/crypto_aead/comet128chamv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.c b/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.h b/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/api.h b/comet/Implementations/crypto_aead/comet64chamv1/rhys/api.h new file mode 100644 index 0000000..9f9959f --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 15 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.c b/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.c new file mode 100644 index 0000000..d068de2 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.c @@ -0,0 +1,607 @@ +/* + * 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 "comet.h" +#include "internal-cham.h" +#include "internal-util.h" +#include + +aead_cipher_t const comet_128_cham_cipher = { + "COMET-128_CHAM-128/128", + COMET_KEY_SIZE, + COMET_128_NONCE_SIZE, + COMET_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_128_cham_aead_encrypt, + comet_128_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_cham_cipher = { + "COMET-64_CHAM-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_cham_aead_encrypt, + comet_64_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_speck_cipher = { + "COMET-64_SPECK-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_speck_aead_encrypt, + comet_64_speck_aead_decrypt +}; + +/** + * \brief Adjusts the Z state to generate the key to use on the next block. + * + * \param Z The Z state to be adjusted. + */ +static void comet_adjust_block_key(unsigned char Z[16]) +{ + /* Doubles the 64-bit prefix to Z in the F(2^64) field */ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)(Z[7])) >> 7); + for (index = 7; index > 0; --index) + Z[index] = (Z[index] << 1) | (Z[index - 1] >> 7); + Z[0] = (Z[0] << 1) ^ (mask & 0x1B); +} + +/* Function prototype for the encrypt function of the underyling cipher */ +typedef void (*comet_encrypt_block_t) + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Processes the associated data for COMET. + * + * \param Y Internal COMET block state of \a block_size bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param block_size Size of the block for the underlying cipher. + * \param encrypt Encryption function for the underlying cipher. + * \param ad Points to the associated data. + * \param adlen Number of bytes of associated data; must be >= 1. + */ +static void comet_process_ad + (unsigned char *Y, unsigned char Z[16], unsigned block_size, + comet_encrypt_block_t encrypt, const unsigned char *ad, + unsigned long long adlen) +{ + /* Domain separator for associated data */ + Z[15] ^= 0x08; + + /* Process all associated data blocks except the last partial block */ + while (adlen >= block_size) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, block_size); + ad += block_size; + adlen -= block_size; + } + + /* Pad and process the partial block on the end */ + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + Z[15] ^= 0x10; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Shuffles the words in a 128-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_128 + (unsigned char out[16], const unsigned char in[16]) +{ + uint32_t x0, x1, x2, x3; + x0 = le_load_word32(in); + x1 = le_load_word32(in + 4); + x2 = le_load_word32(in + 8); + x3 = le_load_word32(in + 12); + le_store_word32(out, x3); + le_store_word32(out + 4, rightRotate1(x2)); + le_store_word32(out + 8, x0); + le_store_word32(out + 12, x1); +} + +/** + * \brief Shuffles the words in a 64-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_64 + (unsigned char out[8], const unsigned char in[8]) +{ + uint32_t x01 = le_load_word32(in); + uint16_t x2 = ((uint16_t)(in[4])) | (((uint16_t)(in[5])) << 8); + out[0] = in[6]; + out[1] = in[7]; + x2 = (x2 >> 1) | (x2 << 15); + out[2] = (uint8_t)x2; + out[3] = (uint8_t)(x2 >> 8); + le_store_word32(out + 4, x01); +} + +/** + * \brief Encrypts the plaintext with COMET-128 to produce the ciphertext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, 16); + lw_xor_block_2_src(c, m, Ys, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Encrypts the plaintext with COMET-64 to produce the ciphertext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, 8); + lw_xor_block_2_src(c, m, Ys, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-128 to produce the plaintext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 16); + lw_xor_block(Y, m, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-64 to produce the plaintext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 8); + lw_xor_block(Y, m, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_128(Y, Z, cham128_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_128_TAG_SIZE) + return -1; + *mlen = clen - COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_128_TAG_SIZE) + comet_decrypt_128(Y, Z, cham128_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_128_TAG_SIZE); +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, cham64_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, cham64_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} + +/** + * \brief Encrypts a 64-bit block with SPECK-64-128 in COMET byte order. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \note This version differs from standard SPECK-64 in that it uses the + * little-endian byte order from the COMET specification which is different + * from the big-endian byte order from the original SPECK paper. + */ +static void speck64_128_comet_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t l[4]; + uint32_t x, y, s; + uint8_t round; + uint8_t li_in = 0; + uint8_t li_out = 3; + + /* Unpack the key and the input block */ + s = le_load_word32(key); + l[0] = le_load_word32(key + 4); + l[1] = le_load_word32(key + 8); + l[2] = le_load_word32(key + 12); + y = le_load_word32(input); + x = le_load_word32(input + 4); + + /* Perform all encryption rounds except the last */ + for (round = 0; round < 26; ++round) { + /* Perform the round with the current key schedule word */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + + /* Calculate the next key schedule word */ + l[li_out] = (s + rightRotate8(l[li_in])) ^ round; + s = leftRotate3(s) ^ l[li_out]; + li_in = (li_in + 1) & 0x03; + li_out = (li_out + 1) & 0x03; + } + + /* Perform the last encryption round and write the result to the output */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + le_store_word32(output, y); + le_store_word32(output + 4, x); +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, speck64_128_comet_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, speck64_128_comet_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.h b/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.h new file mode 100644 index 0000000..d1b24a6 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/comet.h @@ -0,0 +1,274 @@ +/* + * 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_COMET_H +#define LWCRYPTO_COMET_H + +#include "aead-common.h" + +/** + * \file comet.h + * \brief COMET authenticated encryption algorithm. + * + * COMET is a family of authenticated encryption algorithms that are + * built around an underlying block cipher. This library implements + * three members of the family: + * + * \li COMET-128_CHAM-128/128 which has a 128-bit key, a 128-bit nonce, + * and a 128-bit tag, built around the CHAM-128/128 block cipher. + * \li COMET-64_CHAM-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the CHAM-64/128 block cipher. + * \li COMET-64_SPECK-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the SPECK-64/128 block cipher. + * + * There is also another family member that is built around AES but + * this library does not implement that version. + * + * References: https://www.isical.ac.in/~lightweight/comet/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all COMET family members. + */ +#define COMET_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for the 128-bit versions of COMET. + */ +#define COMET_128_TAG_SIZE 16 + +/** + * \brief Size of the authentication tag for the 64-bit versions of COMET. + */ +#define COMET_64_TAG_SIZE 8 + +/** + * \brief Size of the nonce for the 128-bit versions of COMET. + */ +#define COMET_128_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for the 64-bit versions of COMET. + */ +#define COMET_64_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the COMET-128_CHAM-128/128 cipher. + */ +extern aead_cipher_t const comet_128_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_CHAM-64/128 cipher. + */ +extern aead_cipher_t const comet_64_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_SPECK-64/128 cipher. + */ +extern aead_cipher_t const comet_64_speck_cipher; + +/** + * \brief Encrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_128_cham_aead_decrypt() + */ +int comet_128_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_128_cham_aead_encrypt() + */ +int comet_128_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_cham_aead_decrypt() + */ +int comet_64_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_cham_aead_encrypt() + */ +int comet_64_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_speck_aead_decrypt() + */ +int comet_64_speck_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_speck_aead_encrypt() + */ +int comet_64_speck_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/encrypt.c b/comet/Implementations/crypto_aead/comet64chamv1/rhys/encrypt.c new file mode 100644 index 0000000..e832eac --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "comet.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 comet_64_cham_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 comet_64_cham_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.c b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.c new file mode 100644 index 0000000..e097dbd --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.c @@ -0,0 +1,134 @@ +/* + * 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 "internal-cham.h" +#include "internal-util.h" + +void cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t x0, x1, x2, x3; + uint32_t k[8]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word32(key); + k[1] = le_load_word32(key + 4); + k[2] = le_load_word32(key + 8); + k[3] = le_load_word32(key + 12); + k[4] = k[1] ^ leftRotate1(k[1]) ^ leftRotate11(k[1]); + k[5] = k[0] ^ leftRotate1(k[0]) ^ leftRotate11(k[0]); + k[6] = k[3] ^ leftRotate1(k[3]) ^ leftRotate11(k[3]); + k[7] = k[2] ^ leftRotate1(k[2]) ^ leftRotate11(k[2]); + k[0] ^= leftRotate1(k[0]) ^ leftRotate8(k[0]); + k[1] ^= leftRotate1(k[1]) ^ leftRotate8(k[1]); + k[2] ^= leftRotate1(k[2]) ^ leftRotate8(k[2]); + k[3] ^= leftRotate1(k[3]) ^ leftRotate8(k[3]); + + /* Unpack the input block */ + x0 = le_load_word32(input); + x1 = le_load_word32(input + 4); + x2 = le_load_word32(input + 8); + x3 = le_load_word32(input + 12); + + /* Perform the 80 rounds eight at a time */ + for (round = 0; round < 80; round += 8) { + x0 = leftRotate8((x0 ^ round) + (leftRotate1(x1) ^ k[0])); + x1 = leftRotate1((x1 ^ (round + 1)) + (leftRotate8(x2) ^ k[1])); + x2 = leftRotate8((x2 ^ (round + 2)) + (leftRotate1(x3) ^ k[2])); + x3 = leftRotate1((x3 ^ (round + 3)) + (leftRotate8(x0) ^ k[3])); + x0 = leftRotate8((x0 ^ (round + 4)) + (leftRotate1(x1) ^ k[4])); + x1 = leftRotate1((x1 ^ (round + 5)) + (leftRotate8(x2) ^ k[5])); + x2 = leftRotate8((x2 ^ (round + 6)) + (leftRotate1(x3) ^ k[6])); + x3 = leftRotate1((x3 ^ (round + 7)) + (leftRotate8(x0) ^ k[7])); + } + + /* Pack the state into the output block */ + le_store_word32(output, x0); + le_store_word32(output + 4, x1); + le_store_word32(output + 8, x2); + le_store_word32(output + 12, x3); +} + +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint16_t x0, x1, x2, x3; + uint16_t k[16]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word16(key); + k[1] = le_load_word16(key + 2); + k[2] = le_load_word16(key + 4); + k[3] = le_load_word16(key + 6); + k[4] = le_load_word16(key + 8); + k[5] = le_load_word16(key + 10); + k[6] = le_load_word16(key + 12); + k[7] = le_load_word16(key + 14); + k[8] = k[1] ^ leftRotate1_16(k[1]) ^ leftRotate11_16(k[1]); + k[9] = k[0] ^ leftRotate1_16(k[0]) ^ leftRotate11_16(k[0]); + k[10] = k[3] ^ leftRotate1_16(k[3]) ^ leftRotate11_16(k[3]); + k[11] = k[2] ^ leftRotate1_16(k[2]) ^ leftRotate11_16(k[2]); + k[12] = k[5] ^ leftRotate1_16(k[5]) ^ leftRotate11_16(k[5]); + k[13] = k[4] ^ leftRotate1_16(k[4]) ^ leftRotate11_16(k[4]); + k[14] = k[7] ^ leftRotate1_16(k[7]) ^ leftRotate11_16(k[7]); + k[15] = k[6] ^ leftRotate1_16(k[6]) ^ leftRotate11_16(k[6]); + k[0] ^= leftRotate1_16(k[0]) ^ leftRotate8_16(k[0]); + k[1] ^= leftRotate1_16(k[1]) ^ leftRotate8_16(k[1]); + k[2] ^= leftRotate1_16(k[2]) ^ leftRotate8_16(k[2]); + k[3] ^= leftRotate1_16(k[3]) ^ leftRotate8_16(k[3]); + k[4] ^= leftRotate1_16(k[4]) ^ leftRotate8_16(k[4]); + k[5] ^= leftRotate1_16(k[5]) ^ leftRotate8_16(k[5]); + k[6] ^= leftRotate1_16(k[6]) ^ leftRotate8_16(k[6]); + k[7] ^= leftRotate1_16(k[7]) ^ leftRotate8_16(k[7]); + + /* Unpack the input block */ + x0 = le_load_word16(input); + x1 = le_load_word16(input + 2); + x2 = le_load_word16(input + 4); + x3 = le_load_word16(input + 6); + + /* Perform the 80 rounds four at a time */ + for (round = 0; round < 80; round += 4) { + x0 = leftRotate8_16 + ((x0 ^ round) + + (leftRotate1_16(x1) ^ k[round % 16])); + x1 = leftRotate1_16 + ((x1 ^ (round + 1)) + + (leftRotate8_16(x2) ^ k[(round + 1) % 16])); + x2 = leftRotate8_16 + ((x2 ^ (round + 2)) + + (leftRotate1_16(x3) ^ k[(round + 2) % 16])); + x3 = leftRotate1_16 + ((x3 ^ (round + 3)) + + (leftRotate8_16(x0) ^ k[(round + 3) % 16])); + } + + /* Pack the state into the output block */ + le_store_word16(output, x0); + le_store_word16(output + 2, x1); + le_store_word16(output + 4, x2); + le_store_word16(output + 6, x3); +} diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.h b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.h new file mode 100644 index 0000000..29d5ccf --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-cham.h @@ -0,0 +1,67 @@ +/* + * 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_CHAM_H +#define LW_INTERNAL_CHAM_H + +/** + * \file internal-cham.h + * \brief CHAM block cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a 128-bit block with CHAM-128-128. + * + * \param key Points to the 16 bytes of the key. + * \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 cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with CHAM-64-128. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-util.h b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64chamv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.c b/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.h b/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/api.h b/comet/Implementations/crypto_aead/comet64speckv1/rhys/api.h new file mode 100644 index 0000000..9f9959f --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 15 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.c b/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.c new file mode 100644 index 0000000..d068de2 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.c @@ -0,0 +1,607 @@ +/* + * 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 "comet.h" +#include "internal-cham.h" +#include "internal-util.h" +#include + +aead_cipher_t const comet_128_cham_cipher = { + "COMET-128_CHAM-128/128", + COMET_KEY_SIZE, + COMET_128_NONCE_SIZE, + COMET_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_128_cham_aead_encrypt, + comet_128_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_cham_cipher = { + "COMET-64_CHAM-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_cham_aead_encrypt, + comet_64_cham_aead_decrypt +}; + +aead_cipher_t const comet_64_speck_cipher = { + "COMET-64_SPECK-64/128", + COMET_KEY_SIZE, + COMET_64_NONCE_SIZE, + COMET_64_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + comet_64_speck_aead_encrypt, + comet_64_speck_aead_decrypt +}; + +/** + * \brief Adjusts the Z state to generate the key to use on the next block. + * + * \param Z The Z state to be adjusted. + */ +static void comet_adjust_block_key(unsigned char Z[16]) +{ + /* Doubles the 64-bit prefix to Z in the F(2^64) field */ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)(Z[7])) >> 7); + for (index = 7; index > 0; --index) + Z[index] = (Z[index] << 1) | (Z[index - 1] >> 7); + Z[0] = (Z[0] << 1) ^ (mask & 0x1B); +} + +/* Function prototype for the encrypt function of the underyling cipher */ +typedef void (*comet_encrypt_block_t) + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Processes the associated data for COMET. + * + * \param Y Internal COMET block state of \a block_size bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param block_size Size of the block for the underlying cipher. + * \param encrypt Encryption function for the underlying cipher. + * \param ad Points to the associated data. + * \param adlen Number of bytes of associated data; must be >= 1. + */ +static void comet_process_ad + (unsigned char *Y, unsigned char Z[16], unsigned block_size, + comet_encrypt_block_t encrypt, const unsigned char *ad, + unsigned long long adlen) +{ + /* Domain separator for associated data */ + Z[15] ^= 0x08; + + /* Process all associated data blocks except the last partial block */ + while (adlen >= block_size) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, block_size); + ad += block_size; + adlen -= block_size; + } + + /* Pad and process the partial block on the end */ + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + Z[15] ^= 0x10; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + lw_xor_block(Y, ad, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Shuffles the words in a 128-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_128 + (unsigned char out[16], const unsigned char in[16]) +{ + uint32_t x0, x1, x2, x3; + x0 = le_load_word32(in); + x1 = le_load_word32(in + 4); + x2 = le_load_word32(in + 8); + x3 = le_load_word32(in + 12); + le_store_word32(out, x3); + le_store_word32(out + 4, rightRotate1(x2)); + le_store_word32(out + 8, x0); + le_store_word32(out + 12, x1); +} + +/** + * \brief Shuffles the words in a 64-bit block. + * + * \param out The output block after shuffling. + * \param in The input block to be shuffled. + */ +STATIC_INLINE void comet_shuffle_block_64 + (unsigned char out[8], const unsigned char in[8]) +{ + uint32_t x01 = le_load_word32(in); + uint16_t x2 = ((uint16_t)(in[4])) | (((uint16_t)(in[5])) << 8); + out[0] = in[6]; + out[1] = in[7]; + x2 = (x2 >> 1) | (x2 << 15); + out[2] = (uint8_t)x2; + out[3] = (uint8_t)(x2 >> 8); + le_store_word32(out + 4, x01); +} + +/** + * \brief Encrypts the plaintext with COMET-128 to produce the ciphertext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, 16); + lw_xor_block_2_src(c, m, Ys, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Encrypts the plaintext with COMET-64 to produce the ciphertext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param c Ciphertext on output. + * \param m Plaintext message on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_encrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, 8); + lw_xor_block_2_src(c, m, Ys, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block(Y, m, temp); + lw_xor_block_2_src(c, m, Ys, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-128 to produce the plaintext. + * + * \param Y Internal COMET block state of 16 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_128 + (unsigned char Y[16], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[16]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 16) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 16); + lw_xor_block(Y, m, 16); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_128(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +/** + * \brief Decrypts the ciphertext with COMET-64 to produce the plaintext. + * + * \param Y Internal COMET block state of 8 bytes in size. + * \param Z Internal COMET key state of 16 bytes in size. + * \param encrypt Encryption function for the underlying cipher. + * \param m Plaintext message on output. + * \param c Ciphertext on input. + * \param mlen Length of the plaintext message and the ciphertext. + */ +static void comet_decrypt_64 + (unsigned char Y[8], unsigned char Z[16], + comet_encrypt_block_t encrypt, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char Ys[8]; + + /* Domain separator for payload data */ + Z[15] ^= 0x20; + + /* Process all payload data blocks except the last partial block */ + while (mlen >= 8) { + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, 8); + lw_xor_block(Y, m, 8); + c += 8; + m += 8; + mlen -= 8; + } + + /* Pad and process the partial block on the end */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + Z[15] ^= 0x40; + comet_adjust_block_key(Z); + encrypt(Z, Y, Y); + comet_shuffle_block_64(Ys, Y); + lw_xor_block_2_src(m, c, Ys, temp); + lw_xor_block(Y, m, temp); + Y[temp] ^= 0x01; + } +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_128(Y, Z, cham128_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_128_cham_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) +{ + unsigned char Y[16]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_128_TAG_SIZE) + return -1; + *mlen = clen - COMET_128_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memcpy(Y, k, 16); + cham128_128_encrypt(Y, Z, npub); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 16, cham128_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_128_TAG_SIZE) + comet_decrypt_128(Y, Z, cham128_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham128_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_128_TAG_SIZE); +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, cham64_128_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_cham_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + cham64_128_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, cham64_128_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, cham64_128_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + cham64_128_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} + +/** + * \brief Encrypts a 64-bit block with SPECK-64-128 in COMET byte order. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \note This version differs from standard SPECK-64 in that it uses the + * little-endian byte order from the COMET specification which is different + * from the big-endian byte order from the original SPECK paper. + */ +static void speck64_128_comet_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t l[4]; + uint32_t x, y, s; + uint8_t round; + uint8_t li_in = 0; + uint8_t li_out = 3; + + /* Unpack the key and the input block */ + s = le_load_word32(key); + l[0] = le_load_word32(key + 4); + l[1] = le_load_word32(key + 8); + l[2] = le_load_word32(key + 12); + y = le_load_word32(input); + x = le_load_word32(input + 4); + + /* Perform all encryption rounds except the last */ + for (round = 0; round < 26; ++round) { + /* Perform the round with the current key schedule word */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + + /* Calculate the next key schedule word */ + l[li_out] = (s + rightRotate8(l[li_in])) ^ round; + s = leftRotate3(s) ^ l[li_out]; + li_in = (li_in + 1) & 0x03; + li_out = (li_out + 1) & 0x03; + } + + /* Perform the last encryption round and write the result to the output */ + x = (rightRotate8(x) + y) ^ s; + y = leftRotate3(y) ^ x; + le_store_word32(output, y); + le_store_word32(output + 4, x); +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + comet_encrypt_64(Y, Z, speck64_128_comet_encrypt, c, m, mlen); + + /* Generate the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, c + mlen, Y); + return 0; +} + +int comet_64_speck_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) +{ + unsigned char Y[8]; + unsigned char Z[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < COMET_64_TAG_SIZE) + return -1; + *mlen = clen - COMET_64_TAG_SIZE; + + /* Set up the initial state of Y and Z */ + memset(Y, 0, 8); + speck64_128_comet_encrypt(k, Y, Y); + memcpy(Z, npub, 15); + Z[15] = 0; + lw_xor_block(Z, k, 16); + + /* Process the associated data */ + if (adlen > 0) + comet_process_ad(Y, Z, 8, speck64_128_comet_encrypt, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > COMET_64_TAG_SIZE) + comet_decrypt_64(Y, Z, speck64_128_comet_encrypt, m, c, *mlen); + + /* Check the authentication tag */ + Z[15] ^= 0x80; + comet_adjust_block_key(Z); + speck64_128_comet_encrypt(Z, Y, Y); + return aead_check_tag(m, *mlen, Y, c + *mlen, COMET_64_TAG_SIZE); +} diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.h b/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.h new file mode 100644 index 0000000..d1b24a6 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/comet.h @@ -0,0 +1,274 @@ +/* + * 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_COMET_H +#define LWCRYPTO_COMET_H + +#include "aead-common.h" + +/** + * \file comet.h + * \brief COMET authenticated encryption algorithm. + * + * COMET is a family of authenticated encryption algorithms that are + * built around an underlying block cipher. This library implements + * three members of the family: + * + * \li COMET-128_CHAM-128/128 which has a 128-bit key, a 128-bit nonce, + * and a 128-bit tag, built around the CHAM-128/128 block cipher. + * \li COMET-64_CHAM-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the CHAM-64/128 block cipher. + * \li COMET-64_SPECK-64/128 which has a 128-bit key, a 120-bit nonce, + * and a 64-bit tag, built around the SPECK-64/128 block cipher. + * + * There is also another family member that is built around AES but + * this library does not implement that version. + * + * References: https://www.isical.ac.in/~lightweight/comet/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all COMET family members. + */ +#define COMET_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for the 128-bit versions of COMET. + */ +#define COMET_128_TAG_SIZE 16 + +/** + * \brief Size of the authentication tag for the 64-bit versions of COMET. + */ +#define COMET_64_TAG_SIZE 8 + +/** + * \brief Size of the nonce for the 128-bit versions of COMET. + */ +#define COMET_128_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for the 64-bit versions of COMET. + */ +#define COMET_64_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the COMET-128_CHAM-128/128 cipher. + */ +extern aead_cipher_t const comet_128_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_CHAM-64/128 cipher. + */ +extern aead_cipher_t const comet_64_cham_cipher; + +/** + * \brief Meta-information block for the COMET-64_SPECK-64/128 cipher. + */ +extern aead_cipher_t const comet_64_speck_cipher; + +/** + * \brief Encrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_128_cham_aead_decrypt() + */ +int comet_128_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-128_CHAM-128/128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_128_cham_aead_encrypt() + */ +int comet_128_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_cham_aead_decrypt() + */ +int comet_64_cham_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_CHAM-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_cham_aead_encrypt() + */ +int comet_64_cham_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); + +/** + * \brief Encrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa comet_64_speck_aead_decrypt() + */ +int comet_64_speck_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); + +/** + * \brief Decrypts and authenticates a packet with COMET-64_SPECK-64/128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa comet_64_speck_aead_encrypt() + */ +int comet_64_speck_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/encrypt.c b/comet/Implementations/crypto_aead/comet64speckv1/rhys/encrypt.c new file mode 100644 index 0000000..dc4f508 --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "comet.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 comet_64_speck_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 comet_64_speck_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.c b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.c new file mode 100644 index 0000000..e097dbd --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.c @@ -0,0 +1,134 @@ +/* + * 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 "internal-cham.h" +#include "internal-util.h" + +void cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint32_t x0, x1, x2, x3; + uint32_t k[8]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word32(key); + k[1] = le_load_word32(key + 4); + k[2] = le_load_word32(key + 8); + k[3] = le_load_word32(key + 12); + k[4] = k[1] ^ leftRotate1(k[1]) ^ leftRotate11(k[1]); + k[5] = k[0] ^ leftRotate1(k[0]) ^ leftRotate11(k[0]); + k[6] = k[3] ^ leftRotate1(k[3]) ^ leftRotate11(k[3]); + k[7] = k[2] ^ leftRotate1(k[2]) ^ leftRotate11(k[2]); + k[0] ^= leftRotate1(k[0]) ^ leftRotate8(k[0]); + k[1] ^= leftRotate1(k[1]) ^ leftRotate8(k[1]); + k[2] ^= leftRotate1(k[2]) ^ leftRotate8(k[2]); + k[3] ^= leftRotate1(k[3]) ^ leftRotate8(k[3]); + + /* Unpack the input block */ + x0 = le_load_word32(input); + x1 = le_load_word32(input + 4); + x2 = le_load_word32(input + 8); + x3 = le_load_word32(input + 12); + + /* Perform the 80 rounds eight at a time */ + for (round = 0; round < 80; round += 8) { + x0 = leftRotate8((x0 ^ round) + (leftRotate1(x1) ^ k[0])); + x1 = leftRotate1((x1 ^ (round + 1)) + (leftRotate8(x2) ^ k[1])); + x2 = leftRotate8((x2 ^ (round + 2)) + (leftRotate1(x3) ^ k[2])); + x3 = leftRotate1((x3 ^ (round + 3)) + (leftRotate8(x0) ^ k[3])); + x0 = leftRotate8((x0 ^ (round + 4)) + (leftRotate1(x1) ^ k[4])); + x1 = leftRotate1((x1 ^ (round + 5)) + (leftRotate8(x2) ^ k[5])); + x2 = leftRotate8((x2 ^ (round + 6)) + (leftRotate1(x3) ^ k[6])); + x3 = leftRotate1((x3 ^ (round + 7)) + (leftRotate8(x0) ^ k[7])); + } + + /* Pack the state into the output block */ + le_store_word32(output, x0); + le_store_word32(output + 4, x1); + le_store_word32(output + 8, x2); + le_store_word32(output + 12, x3); +} + +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input) +{ + uint16_t x0, x1, x2, x3; + uint16_t k[16]; + uint8_t round; + + /* Unpack the key and generate the key schedule */ + k[0] = le_load_word16(key); + k[1] = le_load_word16(key + 2); + k[2] = le_load_word16(key + 4); + k[3] = le_load_word16(key + 6); + k[4] = le_load_word16(key + 8); + k[5] = le_load_word16(key + 10); + k[6] = le_load_word16(key + 12); + k[7] = le_load_word16(key + 14); + k[8] = k[1] ^ leftRotate1_16(k[1]) ^ leftRotate11_16(k[1]); + k[9] = k[0] ^ leftRotate1_16(k[0]) ^ leftRotate11_16(k[0]); + k[10] = k[3] ^ leftRotate1_16(k[3]) ^ leftRotate11_16(k[3]); + k[11] = k[2] ^ leftRotate1_16(k[2]) ^ leftRotate11_16(k[2]); + k[12] = k[5] ^ leftRotate1_16(k[5]) ^ leftRotate11_16(k[5]); + k[13] = k[4] ^ leftRotate1_16(k[4]) ^ leftRotate11_16(k[4]); + k[14] = k[7] ^ leftRotate1_16(k[7]) ^ leftRotate11_16(k[7]); + k[15] = k[6] ^ leftRotate1_16(k[6]) ^ leftRotate11_16(k[6]); + k[0] ^= leftRotate1_16(k[0]) ^ leftRotate8_16(k[0]); + k[1] ^= leftRotate1_16(k[1]) ^ leftRotate8_16(k[1]); + k[2] ^= leftRotate1_16(k[2]) ^ leftRotate8_16(k[2]); + k[3] ^= leftRotate1_16(k[3]) ^ leftRotate8_16(k[3]); + k[4] ^= leftRotate1_16(k[4]) ^ leftRotate8_16(k[4]); + k[5] ^= leftRotate1_16(k[5]) ^ leftRotate8_16(k[5]); + k[6] ^= leftRotate1_16(k[6]) ^ leftRotate8_16(k[6]); + k[7] ^= leftRotate1_16(k[7]) ^ leftRotate8_16(k[7]); + + /* Unpack the input block */ + x0 = le_load_word16(input); + x1 = le_load_word16(input + 2); + x2 = le_load_word16(input + 4); + x3 = le_load_word16(input + 6); + + /* Perform the 80 rounds four at a time */ + for (round = 0; round < 80; round += 4) { + x0 = leftRotate8_16 + ((x0 ^ round) + + (leftRotate1_16(x1) ^ k[round % 16])); + x1 = leftRotate1_16 + ((x1 ^ (round + 1)) + + (leftRotate8_16(x2) ^ k[(round + 1) % 16])); + x2 = leftRotate8_16 + ((x2 ^ (round + 2)) + + (leftRotate1_16(x3) ^ k[(round + 2) % 16])); + x3 = leftRotate1_16 + ((x3 ^ (round + 3)) + + (leftRotate8_16(x0) ^ k[(round + 3) % 16])); + } + + /* Pack the state into the output block */ + le_store_word16(output, x0); + le_store_word16(output + 2, x1); + le_store_word16(output + 4, x2); + le_store_word16(output + 6, x3); +} diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.h b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.h new file mode 100644 index 0000000..29d5ccf --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-cham.h @@ -0,0 +1,67 @@ +/* + * 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_CHAM_H +#define LW_INTERNAL_CHAM_H + +/** + * \file internal-cham.h + * \brief CHAM block cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a 128-bit block with CHAM-128-128. + * + * \param key Points to the 16 bytes of the key. + * \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 cham128_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with CHAM-64-128. + * + * \param key Points to the 16 bytes of the key. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void cham64_128_encrypt + (const unsigned char *key, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-util.h b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/comet/Implementations/crypto_aead/comet64speckv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.c b/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.h b/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/api.h b/drygascon/Implementations/crypto_aead/drygascon128/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.c b/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.c new file mode 100644 index 0000000..e963903 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.c @@ -0,0 +1,421 @@ +/* + * 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 "drygascon.h" +#include "internal-drysponge.h" +#include + +aead_cipher_t const drygascon128_cipher = { + "DryGASCON128", + DRYGASCON128_KEY_SIZE, + DRYGASCON128_NONCE_SIZE, + DRYGASCON128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon128_aead_encrypt, + drygascon128_aead_decrypt +}; + +aead_cipher_t const drygascon256_cipher = { + "DryGASCON256", + DRYGASCON256_KEY_SIZE, + DRYGASCON256_NONCE_SIZE, + DRYGASCON256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon256_aead_encrypt, + drygascon256_aead_decrypt +}; + +aead_hash_algorithm_t const drygascon128_hash_algorithm = { + "DryGASCON128-HASH", + sizeof(int), + DRYGASCON128_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon128_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 drygascon256_hash_algorithm = { + "DryGASCON256-HASH", + sizeof(int), + DRYGASCON256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon256_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 Processes associated data for DryGASCON128. + * + * \param state DrySPONGE128 sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must not be zero. + * \param finalize Non-zero to finalize packet processing because + * the message is zero-length. + */ +static void drygascon128_process_ad + (drysponge128_state_t *state, const unsigned char *ad, + unsigned long long adlen, int finalize) +{ + /* Process all blocks except the last one */ + while (adlen > DRYSPONGE128_RATE) { + drysponge128_f_absorb(state, ad, DRYSPONGE128_RATE); + drysponge128_g_core(state); + ad += DRYSPONGE128_RATE; + adlen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state->domain = DRYDOMAIN128_ASSOC_DATA; + if (finalize) + state->domain |= DRYDOMAIN128_FINAL; + if (adlen < DRYSPONGE128_RATE) + state->domain |= DRYDOMAIN128_PADDED; + drysponge128_f_absorb(state, ad, (unsigned)adlen); + drysponge128_g(state); +} + +/** + * \brief Processes associated data for DryGASCON256. + * + * \param state DrySPONGE256 sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must not be zero. + * \param finalize Non-zero to finalize packet processing because + * the message is zero-length. + */ +static void drygascon256_process_ad + (drysponge256_state_t *state, const unsigned char *ad, + unsigned long long adlen, int finalize) +{ + /* Process all blocks except the last one */ + while (adlen > DRYSPONGE256_RATE) { + drysponge256_f_absorb(state, ad, DRYSPONGE256_RATE); + drysponge256_g_core(state); + ad += DRYSPONGE256_RATE; + adlen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state->domain = DRYDOMAIN256_ASSOC_DATA; + if (finalize) + state->domain |= DRYDOMAIN256_FINAL; + if (adlen < DRYSPONGE256_RATE) + state->domain |= DRYDOMAIN256_PADDED; + drysponge256_f_absorb(state, ad, (unsigned)adlen); + drysponge256_g(state); +} + +int drygascon128_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) +{ + drysponge128_state_t state; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DRYGASCON128_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + drysponge128_setup(&state, k, npub, adlen == 0 && mlen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon128_process_ad(&state, ad, adlen, mlen == 0); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + /* Processs all blocks except the last one */ + while (mlen > DRYSPONGE128_RATE) { + drysponge128_f_absorb(&state, m, DRYSPONGE128_RATE); + lw_xor_block_2_src(c, m, state.r.B, DRYSPONGE128_RATE); + drysponge128_g(&state); + c += DRYSPONGE128_RATE; + m += DRYSPONGE128_RATE; + mlen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN128_MESSAGE | DRYDOMAIN128_FINAL; + if (mlen < DRYSPONGE128_RATE) + state.domain |= DRYDOMAIN128_PADDED; + temp = (unsigned)mlen; + drysponge128_f_absorb(&state, m, temp); + lw_xor_block_2_src(c, m, state.r.B, temp); + drysponge128_g(&state); + c += temp; + } + + /* Generate the authentication tag */ + memcpy(c, state.r.B, DRYGASCON128_TAG_SIZE); + return 0; +} + +int drygascon128_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) +{ + drysponge128_state_t state; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DRYGASCON128_TAG_SIZE) + return -1; + *mlen = clen - DRYGASCON128_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + clen -= DRYGASCON128_TAG_SIZE; + drysponge128_setup(&state, k, npub, adlen == 0 && clen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon128_process_ad(&state, ad, adlen, clen == 0); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + /* Processs all blocks except the last one */ + while (clen > DRYSPONGE128_RATE) { + lw_xor_block_2_src(m, c, state.r.B, DRYSPONGE128_RATE); + drysponge128_f_absorb(&state, m, DRYSPONGE128_RATE); + drysponge128_g(&state); + c += DRYSPONGE128_RATE; + m += DRYSPONGE128_RATE; + clen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN128_MESSAGE | DRYDOMAIN128_FINAL; + if (clen < DRYSPONGE128_RATE) + state.domain |= DRYDOMAIN128_PADDED; + temp = (unsigned)clen; + lw_xor_block_2_src(m, c, state.r.B, temp); + drysponge128_f_absorb(&state, m, temp); + drysponge128_g(&state); + c += temp; + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state.r.B, c, DRYGASCON128_TAG_SIZE); +} + +int drygascon256_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) +{ + drysponge256_state_t state; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DRYGASCON256_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + drysponge256_setup(&state, k, npub, adlen == 0 && mlen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon256_process_ad(&state, ad, adlen, mlen == 0); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + /* Processs all blocks except the last one */ + while (mlen > DRYSPONGE256_RATE) { + drysponge256_f_absorb(&state, m, DRYSPONGE256_RATE); + lw_xor_block_2_src(c, m, state.r.B, DRYSPONGE256_RATE); + drysponge256_g(&state); + c += DRYSPONGE256_RATE; + m += DRYSPONGE256_RATE; + mlen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN256_MESSAGE | DRYDOMAIN256_FINAL; + if (mlen < DRYSPONGE256_RATE) + state.domain |= DRYDOMAIN256_PADDED; + temp = (unsigned)mlen; + drysponge256_f_absorb(&state, m, temp); + lw_xor_block_2_src(c, m, state.r.B, temp); + drysponge256_g(&state); + c += temp; + } + + /* Generate the authentication tag */ + memcpy(c, state.r.B, 16); + drysponge256_g(&state); + memcpy(c + 16, state.r.B, 16); + return 0; +} + +int drygascon256_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) +{ + drysponge256_state_t state; + unsigned char *mtemp = m; + unsigned temp; + int result; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DRYGASCON256_TAG_SIZE) + return -1; + *mlen = clen - DRYGASCON256_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + clen -= DRYGASCON256_TAG_SIZE; + drysponge256_setup(&state, k, npub, adlen == 0 && clen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon256_process_ad(&state, ad, adlen, clen == 0); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + /* Processs all blocks except the last one */ + while (clen > DRYSPONGE256_RATE) { + lw_xor_block_2_src(m, c, state.r.B, DRYSPONGE256_RATE); + drysponge256_f_absorb(&state, m, DRYSPONGE256_RATE); + drysponge256_g(&state); + c += DRYSPONGE256_RATE; + m += DRYSPONGE256_RATE; + clen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN256_MESSAGE | DRYDOMAIN256_FINAL; + if (clen < DRYSPONGE256_RATE) + state.domain |= DRYDOMAIN256_PADDED; + temp = (unsigned)clen; + lw_xor_block_2_src(m, c, state.r.B, temp); + drysponge256_f_absorb(&state, m, temp); + drysponge256_g(&state); + c += temp; + } + + /* Check the authentication tag which is split into two pieces */ + result = aead_check_tag(0, 0, state.r.B, c, 16); + drysponge256_g(&state); + return aead_check_tag_precheck + (mtemp, *mlen, state.r.B, c + 16, 16, ~result); +} + +/** + * \brief Precomputed initialization vector for DryGASCON128-HASH. + * + * This is the CST_H value from the DryGASCON specification after it + * has been processed by the key setup function for DrySPONGE128. + */ +static unsigned char const drygascon128_hash_init[] = { + /* c */ + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + /* x */ + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89 +}; + +int drygascon128_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + drysponge128_state_t state; + memcpy(state.c.B, drygascon128_hash_init, sizeof(state.c.B)); + memcpy(state.x.B, drygascon128_hash_init + sizeof(state.c.B), + sizeof(state.x.B)); + state.domain = 0; + state.rounds = DRYSPONGE128_ROUNDS; + drygascon128_process_ad(&state, in, inlen, 1); + memcpy(out, state.r.B, 16); + drysponge128_g(&state); + memcpy(out + 16, state.r.B, 16); + return 0; +} + +/** + * \brief Precomputed initialization vector for DryGASCON256-HASH. + * + * This is the CST_H value from the DryGASCON specification after it + * has been processed by the key setup function for DrySPONGE256. + */ +static unsigned char const drygascon256_hash_init[] = { + /* c */ + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + /* x */ + 0x45, 0x28, 0x21, 0xe6, 0x38, 0xd0, 0x13, 0x77, + 0xbe, 0x54, 0x66, 0xcf, 0x34, 0xe9, 0x0c, 0x6c +}; + +int drygascon256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + drysponge256_state_t state; + memcpy(state.c.B, drygascon256_hash_init, sizeof(state.c.B)); + memcpy(state.x.B, drygascon256_hash_init + sizeof(state.c.B), + sizeof(state.x.B)); + state.domain = 0; + state.rounds = DRYSPONGE256_ROUNDS; + drygascon256_process_ad(&state, in, inlen, 1); + memcpy(out, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 16, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 32, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 48, state.r.B, 16); + return 0; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.h b/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.h new file mode 100644 index 0000000..12e18c3 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/drygascon.h @@ -0,0 +1,264 @@ +/* + * 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_DRYGASCON_H +#define LWCRYPTO_DRYGASCON_H + +#include "aead-common.h" + +/** + * \file drygascon.h + * \brief DryGASCON authenticated encryption algorithm. + * + * DryGASCON is a family of authenticated encryption algorithms based + * around a generalised version of the ASCON permutation. DryGASCON + * is designed to provide some protection against power analysis. + * + * There are four algorithms in the DryGASCON family: + * + * \li DryGASCON128 is an authenticated encryption algorithm with a + * 128-bit key, a 128-bit nonce, and a 128-bit authentication tag. + * \li DryGASCON256 is an authenticated encryption algorithm with a + * 256-bit key, a 128-bit nonce, and a 128-256 authentication tag. + * \li DryGASCON128-HASH is a hash algorithm with a 256-bit output. + * \li DryGASCON256-HASH is a hash algorithm with a 512-bit output. + * + * DryGASCON128 and DryGASCON128-HASH are the primary members of the family. + * + * References: https://github.com/sebastien-riou/DryGASCON + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for DryGASCON128. + */ +#define DRYGASCON128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for DryGASCON128. + */ +#define DRYGASCON128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for DryGASCON128. + */ +#define DRYGASCON128_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for DryGASCON128-HASH. + */ +#define DRYGASCON128_HASH_SIZE 32 + +/** + * \brief Size of the key for DryGASCON256. + */ +#define DRYGASCON256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for DryGASCON256. + */ +#define DRYGASCON256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for DryGASCON256. + */ +#define DRYGASCON256_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for DryGASCON256-HASH. + */ +#define DRYGASCON256_HASH_SIZE 64 + +/** + * \brief Meta-information block for the DryGASCON128 cipher. + */ +extern aead_cipher_t const drygascon128_cipher; + +/** + * \brief Meta-information block for the DryGASCON256 cipher. + */ +extern aead_cipher_t const drygascon256_cipher; + +/** + * \brief Meta-information block for DryGASCON128-HASH. + */ +extern aead_hash_algorithm_t const drygascon128_hash_algorithm; + +/** + * \brief Meta-information block for DryGASCON256-HASH. + */ +extern aead_hash_algorithm_t const drygascon256_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with DryGASCON128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa drygascon128_aead_decrypt() + */ +int drygascon128_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); + +/** + * \brief Decrypts and authenticates a packet with DryGASCON128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa drygascon128_aead_encrypt() + */ +int drygascon128_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); + +/** + * \brief Encrypts and authenticates a packet with DryGASCON256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa drygascon256_aead_decrypt() + */ +int drygascon256_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); + +/** + * \brief Decrypts and authenticates a packet with DryGASCON256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa drygascon256_aead_encrypt() + */ +int drygascon256_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); + +/** + * \brief Hashes a block of input data with DRYGASCON128. + * + * \param out Buffer to receive the hash output which must be at least + * DRYGASCON128_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 drygascon128_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with DRYGASCON256. + * + * \param out Buffer to receive the hash output which must be at least + * DRYGASCON256_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 drygascon256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/encrypt.c b/drygascon/Implementations/crypto_aead/drygascon128/rhys/encrypt.c new file mode 100644 index 0000000..663de84 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "drygascon.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 drygascon128_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 drygascon128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.c b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.c new file mode 100644 index 0000000..67f1b27 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.c @@ -0,0 +1,600 @@ +/* + * 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 "internal-drysponge.h" +#include + +/* Right rotations in bit-interleaved format */ +#define intRightRotateEven(x,bits) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate(_x0, (bits)); \ + _x1 = rightRotate(_x1, (bits)); \ + _x0 | (((uint64_t)_x1) << 32); \ + })) +#define intRightRotateOdd(x,bits) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate(_x0, ((bits) + 1) % 32); \ + _x1 = rightRotate(_x1, (bits)); \ + _x1 | (((uint64_t)_x0) << 32); \ + })) +#define intRightRotate1_64(x) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate1(_x0); \ + _x1 | (((uint64_t)_x0) << 32); \ + })) +#define intRightRotate2_64(x) (intRightRotateEven((x), 1)) +#define intRightRotate3_64(x) (intRightRotateOdd((x), 1)) +#define intRightRotate4_64(x) (intRightRotateEven((x), 2)) +#define intRightRotate5_64(x) (intRightRotateOdd((x), 2)) +#define intRightRotate6_64(x) (intRightRotateEven((x), 3)) +#define intRightRotate7_64(x) (intRightRotateOdd((x), 3)) +#define intRightRotate8_64(x) (intRightRotateEven((x), 4)) +#define intRightRotate9_64(x) (intRightRotateOdd((x), 4)) +#define intRightRotate10_64(x) (intRightRotateEven((x), 5)) +#define intRightRotate11_64(x) (intRightRotateOdd((x), 5)) +#define intRightRotate12_64(x) (intRightRotateEven((x), 6)) +#define intRightRotate13_64(x) (intRightRotateOdd((x), 6)) +#define intRightRotate14_64(x) (intRightRotateEven((x), 7)) +#define intRightRotate15_64(x) (intRightRotateOdd((x), 7)) +#define intRightRotate16_64(x) (intRightRotateEven((x), 8)) +#define intRightRotate17_64(x) (intRightRotateOdd((x), 8)) +#define intRightRotate18_64(x) (intRightRotateEven((x), 9)) +#define intRightRotate19_64(x) (intRightRotateOdd((x), 9)) +#define intRightRotate20_64(x) (intRightRotateEven((x), 10)) +#define intRightRotate21_64(x) (intRightRotateOdd((x), 10)) +#define intRightRotate22_64(x) (intRightRotateEven((x), 11)) +#define intRightRotate23_64(x) (intRightRotateOdd((x), 11)) +#define intRightRotate24_64(x) (intRightRotateEven((x), 12)) +#define intRightRotate25_64(x) (intRightRotateOdd((x), 12)) +#define intRightRotate26_64(x) (intRightRotateEven((x), 13)) +#define intRightRotate27_64(x) (intRightRotateOdd((x), 13)) +#define intRightRotate28_64(x) (intRightRotateEven((x), 14)) +#define intRightRotate29_64(x) (intRightRotateOdd((x), 14)) +#define intRightRotate30_64(x) (intRightRotateEven((x), 15)) +#define intRightRotate31_64(x) (intRightRotateOdd((x), 15)) +#define intRightRotate32_64(x) (intRightRotateEven((x), 16)) +#define intRightRotate33_64(x) (intRightRotateOdd((x), 16)) +#define intRightRotate34_64(x) (intRightRotateEven((x), 17)) +#define intRightRotate35_64(x) (intRightRotateOdd((x), 17)) +#define intRightRotate36_64(x) (intRightRotateEven((x), 18)) +#define intRightRotate37_64(x) (intRightRotateOdd((x), 18)) +#define intRightRotate38_64(x) (intRightRotateEven((x), 19)) +#define intRightRotate39_64(x) (intRightRotateOdd((x), 19)) +#define intRightRotate40_64(x) (intRightRotateEven((x), 20)) +#define intRightRotate41_64(x) (intRightRotateOdd((x), 20)) +#define intRightRotate42_64(x) (intRightRotateEven((x), 21)) +#define intRightRotate43_64(x) (intRightRotateOdd((x), 21)) +#define intRightRotate44_64(x) (intRightRotateEven((x), 22)) +#define intRightRotate45_64(x) (intRightRotateOdd((x), 22)) +#define intRightRotate46_64(x) (intRightRotateEven((x), 23)) +#define intRightRotate47_64(x) (intRightRotateOdd((x), 23)) +#define intRightRotate48_64(x) (intRightRotateEven((x), 24)) +#define intRightRotate49_64(x) (intRightRotateOdd((x), 24)) +#define intRightRotate50_64(x) (intRightRotateEven((x), 25)) +#define intRightRotate51_64(x) (intRightRotateOdd((x), 25)) +#define intRightRotate52_64(x) (intRightRotateEven((x), 26)) +#define intRightRotate53_64(x) (intRightRotateOdd((x), 26)) +#define intRightRotate54_64(x) (intRightRotateEven((x), 27)) +#define intRightRotate55_64(x) (intRightRotateOdd((x), 27)) +#define intRightRotate56_64(x) (intRightRotateEven((x), 28)) +#define intRightRotate57_64(x) (intRightRotateOdd((x), 28)) +#define intRightRotate58_64(x) (intRightRotateEven((x), 29)) +#define intRightRotate59_64(x) (intRightRotateOdd((x), 29)) +#define intRightRotate60_64(x) (intRightRotateEven((x), 30)) +#define intRightRotate61_64(x) (intRightRotateOdd((x), 30)) +#define intRightRotate62_64(x) (intRightRotateEven((x), 31)) +#define intRightRotate63_64(x) (intRightRotateOdd((x), 31)) + +void gascon128_core_round(gascon128_state_t *state, uint8_t round) +{ + uint64_t t0, t1, t2, t3, t4; + + /* Load the state into local varaibles */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); +#endif + + /* Add the round constant to the middle of the state */ + x2 ^= ((0x0F - round) << 4) | round; + + /* Substitution layer */ + x0 ^= x4; x2 ^= x1; x4 ^= x3; t0 = (~x0) & x1; t1 = (~x1) & x2; + t2 = (~x2) & x3; t3 = (~x3) & x4; t4 = (~x4) & x0; x0 ^= t1; + x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; x1 ^= x0; x3 ^= x2; + x0 ^= x4; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= intRightRotate19_64(x0) ^ intRightRotate28_64(x0); + x1 ^= intRightRotate61_64(x1) ^ intRightRotate38_64(x1); + x2 ^= intRightRotate1_64(x2) ^ intRightRotate6_64(x2); + x3 ^= intRightRotate10_64(x3) ^ intRightRotate17_64(x3); + x4 ^= intRightRotate7_64(x4) ^ intRightRotate40_64(x4); + + /* Write the local variables back to the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); +#endif +} + +void gascon256_core_round(gascon256_state_t *state, uint8_t round) +{ + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + + /* Load the state into local varaibles */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; + uint64_t x8 = state->S[8]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); + uint64_t x8 = le_load_word64(state->B + 64); +#endif + + /* Add the round constant to the middle of the state */ + x4 ^= ((0x0F - round) << 4) | round; + + /* Substitution layer */ + x0 ^= x8; x2 ^= x1; x4 ^= x3; x6 ^= x5; x8 ^= x7; t0 = (~x0) & x1; + t1 = (~x1) & x2; t2 = (~x2) & x3; t3 = (~x3) & x4; t4 = (~x4) & x5; + t5 = (~x5) & x6; t6 = (~x6) & x7; t7 = (~x7) & x8; t8 = (~x8) & x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t5; x5 ^= t6; x6 ^= t7; + x7 ^= t8; x8 ^= t0; x1 ^= x0; x3 ^= x2; x5 ^= x4; x7 ^= x6; x0 ^= x8; + x4 = ~x4; + + /* Linear diffusion layer */ + x0 ^= intRightRotate19_64(x0) ^ intRightRotate28_64(x0); + x1 ^= intRightRotate61_64(x1) ^ intRightRotate38_64(x1); + x2 ^= intRightRotate1_64(x2) ^ intRightRotate6_64(x2); + x3 ^= intRightRotate10_64(x3) ^ intRightRotate17_64(x3); + x4 ^= intRightRotate7_64(x4) ^ intRightRotate40_64(x4); + x5 ^= intRightRotate31_64(x5) ^ intRightRotate26_64(x5); + x6 ^= intRightRotate53_64(x6) ^ intRightRotate58_64(x6); + x7 ^= intRightRotate9_64(x7) ^ intRightRotate46_64(x7); + x8 ^= intRightRotate43_64(x8) ^ intRightRotate50_64(x8); + + /* Write the local variables back to the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; + state->S[8] = x8; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); + le_store_word64(state->B + 64, x8); +#endif +} + +void drysponge128_g(drysponge128_state_t *state) +{ + unsigned round; + + /* Perform the first round. For each round we XOR the 16 bytes of + * the output data with the first 16 bytes of the state. And then + * XOR with the next 16 bytes of the state, rotated by 4 bytes */ + gascon128_core_round(&(state->c), 0); + state->r.W[0] = state->c.W[0] ^ state->c.W[5]; + state->r.W[1] = state->c.W[1] ^ state->c.W[6]; + state->r.W[2] = state->c.W[2] ^ state->c.W[7]; + state->r.W[3] = state->c.W[3] ^ state->c.W[4]; + + /* Perform the rest of the rounds */ + for (round = 1; round < state->rounds; ++round) { + gascon128_core_round(&(state->c), round); + state->r.W[0] ^= state->c.W[0] ^ state->c.W[5]; + state->r.W[1] ^= state->c.W[1] ^ state->c.W[6]; + state->r.W[2] ^= state->c.W[2] ^ state->c.W[7]; + state->r.W[3] ^= state->c.W[3] ^ state->c.W[4]; + } +} + +void drysponge256_g(drysponge256_state_t *state) +{ + unsigned round; + + /* Perform the first round. For each round we XOR the 16 bytes of + * the output data with the first 16 bytes of the state. And then + * XOR with the next 16 bytes of the state, rotated by 4 bytes. + * And so on for a total of 64 bytes XOR'ed into the output data. */ + gascon256_core_round(&(state->c), 0); + state->r.W[0] = state->c.W[0] ^ state->c.W[5] ^ + state->c.W[10] ^ state->c.W[15]; + state->r.W[1] = state->c.W[1] ^ state->c.W[6] ^ + state->c.W[11] ^ state->c.W[12]; + state->r.W[2] = state->c.W[2] ^ state->c.W[7] ^ + state->c.W[8] ^ state->c.W[13]; + state->r.W[3] = state->c.W[3] ^ state->c.W[4] ^ + state->c.W[9] ^ state->c.W[14]; + + /* Perform the rest of the rounds */ + for (round = 1; round < state->rounds; ++round) { + gascon256_core_round(&(state->c), round); + state->r.W[0] ^= state->c.W[0] ^ state->c.W[5] ^ + state->c.W[10] ^ state->c.W[15]; + state->r.W[1] ^= state->c.W[1] ^ state->c.W[6] ^ + state->c.W[11] ^ state->c.W[12]; + state->r.W[2] ^= state->c.W[2] ^ state->c.W[7] ^ + state->c.W[8] ^ state->c.W[13]; + state->r.W[3] ^= state->c.W[3] ^ state->c.W[4] ^ + state->c.W[9] ^ state->c.W[14]; + } +} + +void drysponge128_g_core(drysponge128_state_t *state) +{ + unsigned round; + for (round = 0; round < state->rounds; ++round) + gascon128_core_round(&(state->c), round); +} + +void drysponge256_g_core(drysponge256_state_t *state) +{ + unsigned round; + for (round = 0; round < state->rounds; ++round) + gascon256_core_round(&(state->c), round); +} + +/** + * \brief Selects an element of x in constant time. + * + * \param x Points to the four elements of x. + * \param index Index of which element to extract between 0 and 3. + * + * \return The selected element of x. + */ +STATIC_INLINE uint32_t drysponge_select_x(const uint32_t x[4], uint8_t index) +{ + /* We need to be careful how we select each element of x because + * we are doing a data-dependent fetch here. Do the fetch in a way + * that should avoid cache timing issues by fetching every element + * of x and masking away the ones we don't want. + * + * There is a possible side channel here with respect to power analysis. + * The "mask" value will be all-ones for the selected index and all-zeroes + * for the other indexes. This may show up as different power consumption + * for the "result ^= x[i] & mask" statement when i is the selected index. + * Such a side channel could in theory allow reading the plaintext input + * to the cipher by analysing the CPU's power consumption. + * + * The DryGASCON specification acknowledges the possibility of plaintext + * recovery in section 7.4. For software mitigation the specification + * suggests randomization of the indexes into c and x and randomization + * of the order of processing words. We aren't doing that here yet. + * Patches welcome to fix this. + */ + uint32_t mask = -((uint32_t)((0x04 - index) >> 2)); + uint32_t result = x[0] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x01)) >> 2)); + result ^= x[1] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x02)) >> 2)); + result ^= x[2] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x03)) >> 2)); + return result ^ (x[3] & mask); +} + +/** + * \brief Mixes a 32-bit value into the DrySPONGE128 state. + * + * \param state DrySPONGE128 state. + * \param data The data to be mixed in the bottom 10 bits. + */ +static void drysponge128_mix_phase_round + (drysponge128_state_t *state, uint32_t data) +{ + /* Mix in elements from x according to the 2-bit indexes in the data */ + state->c.W[0] ^= drysponge_select_x(state->x.W, data & 0x03); + state->c.W[2] ^= drysponge_select_x(state->x.W, (data >> 2) & 0x03); + state->c.W[4] ^= drysponge_select_x(state->x.W, (data >> 4) & 0x03); + state->c.W[6] ^= drysponge_select_x(state->x.W, (data >> 6) & 0x03); + state->c.W[8] ^= drysponge_select_x(state->x.W, (data >> 8) & 0x03); +} + +/** + * \brief Mixes a 32-bit value into the DrySPONGE256 state. + * + * \param state DrySPONGE256 state. + * \param data The data to be mixed in the bottom 18 bits. + */ +static void drysponge256_mix_phase_round + (drysponge256_state_t *state, uint32_t data) +{ + /* Mix in elements from x according to the 2-bit indexes in the data */ + state->c.W[0] ^= drysponge_select_x(state->x.W, data & 0x03); + state->c.W[2] ^= drysponge_select_x(state->x.W, (data >> 2) & 0x03); + state->c.W[4] ^= drysponge_select_x(state->x.W, (data >> 4) & 0x03); + state->c.W[6] ^= drysponge_select_x(state->x.W, (data >> 6) & 0x03); + state->c.W[8] ^= drysponge_select_x(state->x.W, (data >> 8) & 0x03); + state->c.W[10] ^= drysponge_select_x(state->x.W, (data >> 10) & 0x03); + state->c.W[12] ^= drysponge_select_x(state->x.W, (data >> 12) & 0x03); + state->c.W[14] ^= drysponge_select_x(state->x.W, (data >> 14) & 0x03); + state->c.W[16] ^= drysponge_select_x(state->x.W, (data >> 16) & 0x03); +} + +/** + * \brief Mixes an input block into a DrySPONGE128 state. + * + * \param state The DrySPONGE128 state. + * \param data Full rate block containing the input data. + */ +static void drysponge128_mix_phase + (drysponge128_state_t *state, const unsigned char data[DRYSPONGE128_RATE]) +{ + /* Mix 10-bit groups into the output, with the domain + * separator added to the last two groups */ + drysponge128_mix_phase_round + (state, data[0] | (((uint32_t)(data[1])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[1] >> 2) | (((uint32_t)(data[2])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[2] >> 4) | (((uint32_t)(data[3])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[3] >> 6) | (((uint32_t)(data[4])) << 2)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, data[5] | (((uint32_t)(data[6])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[6] >> 2) | (((uint32_t)(data[7])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[7] >> 4) | (((uint32_t)(data[8])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[8] >> 6) | (((uint32_t)(data[9])) << 2)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, data[10] | (((uint32_t)(data[11])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[11] >> 2) | (((uint32_t)(data[12])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[12] >> 4) | (((uint32_t)(data[13])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, ((data[13] >> 6) | (((uint32_t)(data[14])) << 2))); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round(state, data[15] ^ state->domain); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round(state, state->domain >> 10); + + /* Revert to the default domain separator for the next block */ + state->domain = 0; +} + +/** + * \brief Mixes an input block into a DrySPONGE256 state. + * + * \param state The DrySPONGE256 state. + * \param data Full rate block containing the input data. + */ +static void drysponge256_mix_phase + (drysponge256_state_t *state, const unsigned char data[DRYSPONGE256_RATE]) +{ + /* Mix 18-bit groups into the output, with the domain in the last group */ + drysponge256_mix_phase_round + (state, data[0] | (((uint32_t)(data[1])) << 8) | + (((uint32_t)(data[2])) << 16)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[2] >> 2) | (((uint32_t)(data[3])) << 6) | + (((uint32_t)(data[4])) << 14)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[4] >> 4) | (((uint32_t)(data[5])) << 4) | + (((uint32_t)(data[6])) << 12)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[6] >> 6) | (((uint32_t)(data[7])) << 2) | + (((uint32_t)(data[8])) << 10)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, data[9] | (((uint32_t)(data[10])) << 8) | + (((uint32_t)(data[11])) << 16)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[11] >> 2) | (((uint32_t)(data[12])) << 6) | + (((uint32_t)(data[13])) << 14)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[13] >> 4) | (((uint32_t)(data[14])) << 4) | + (((uint32_t)(data[15])) << 12)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[15] >> 6) ^ state->domain); + + /* Revert to the default domain separator for the next block */ + state->domain = 0; +} + +void drysponge128_f_absorb + (drysponge128_state_t *state, const unsigned char *input, unsigned len) +{ + if (len >= DRYSPONGE128_RATE) { + drysponge128_mix_phase(state, input); + } else { + unsigned char padded[DRYSPONGE128_RATE]; + memcpy(padded, input, len); + padded[len] = 0x01; + memset(padded + len + 1, 0, DRYSPONGE128_RATE - len - 1); + drysponge128_mix_phase(state, padded); + } +} + +void drysponge256_f_absorb + (drysponge256_state_t *state, const unsigned char *input, unsigned len) +{ + if (len >= DRYSPONGE256_RATE) { + drysponge256_mix_phase(state, input); + } else { + unsigned char padded[DRYSPONGE256_RATE]; + memcpy(padded, input, len); + padded[len] = 0x01; + memset(padded + len + 1, 0, DRYSPONGE256_RATE - len - 1); + drysponge256_mix_phase(state, padded); + } +} + +/** + * \brief Determine if some of the words of an "x" value are identical. + * + * \param x Points to the "x" buffer to check. + * + * \return Non-zero if some of the words are the same, zero if they are + * distinct from each other. + * + * We try to perform the check in constant time to avoid giving away + * any information about the value of the key. + */ +static int drysponge_x_words_are_same(const uint32_t x[4]) +{ + unsigned i, j; + int result = 0; + for (i = 0; i < 3; ++i) { + for (j = i + 1; j < 4; ++j) { + uint32_t check = x[i] ^ x[j]; + result |= (int)((0x100000000ULL - check) >> 32); + } + } + return result; +} + +void drysponge128_setup + (drysponge128_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block) +{ + /* Fill the GASCON-128 state with repeated copies of the key */ + memcpy(state->c.B, key, 16); + memcpy(state->c.B + 16, key, 16); + memcpy(state->c.B + 32, key, 8); + + /* Generate the "x" value for the state. All four words of "x" + * must be unique because they will be used in drysponge_select_x() + * as stand-ins for the bit pairs 00, 01, 10, and 11. + * + * Run the core block operation over and over until "x" is unique. + * Technically the runtime here is key-dependent and not constant. + * If the input key is randomized, this should only take 1 round + * on average so it is "almost constant time". + */ + do { + gascon128_core_round(&(state->c), 0); + } while (drysponge_x_words_are_same(state->c.W)); + memcpy(state->x.W, state->c.W, sizeof(state->x)); + + /* Replace the generated "x" value in the state with the key prefix */ + memcpy(state->c.W, key, sizeof(state->x)); + + /* Absorb the nonce into the state with an increased number of rounds */ + state->rounds = DRYSPONGE128_INIT_ROUNDS; + state->domain = DRYDOMAIN128_NONCE; + if (final_block) + state->domain |= DRYDOMAIN128_FINAL; + drysponge128_f_absorb(state, nonce, 16); + drysponge128_g(state); + + /* Set up the normal number of rounds for future operations */ + state->rounds = DRYSPONGE128_ROUNDS; +} + +void drysponge256_setup + (drysponge256_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block) +{ + /* Fill the GASCON-256 state with repeated copies of the key */ + memcpy(state->c.B, key, 32); + memcpy(state->c.B + 32, key, 32); + memcpy(state->c.B + 64, key, 8); + + /* Generate the "x" value for the state */ + do { + gascon256_core_round(&(state->c), 0); + } while (drysponge_x_words_are_same(state->c.W)); + memcpy(state->x.W, state->c.W, sizeof(state->x)); + + /* Replace the generated "x" value in the state with the key prefix */ + memcpy(state->c.W, key, sizeof(state->x)); + + /* Absorb the nonce into the state with an increased number of rounds */ + state->rounds = DRYSPONGE256_INIT_ROUNDS; + state->domain = DRYDOMAIN256_NONCE; + if (final_block) + state->domain |= DRYDOMAIN256_FINAL; + drysponge256_f_absorb(state, nonce, 16); + drysponge256_g(state); + + /* Set up the normal number of rounds for future operations */ + state->rounds = DRYSPONGE256_ROUNDS; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.h b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.h new file mode 100644 index 0000000..05b0c16 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-drysponge.h @@ -0,0 +1,345 @@ +/* + * 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_DRYSPONGE_H +#define LW_INTERNAL_DRYSPONGE_H + +#include "internal-util.h" + +/** + * \file internal-drysponge.h + * \brief Internal implementation of DrySPONGE for the DryGASCON cipher. + * + * References: https://github.com/sebastien-riou/DryGASCON + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the GASCON-128 permutation state in bytes. + */ +#define GASCON128_STATE_SIZE 40 + +/** + * \brief Size of the GASCON-256 permutation state in bytes. + */ +#define GASCON256_STATE_SIZE 72 + +/** + * \brief Rate of absorption and squeezing for DrySPONGE128. + */ +#define DRYSPONGE128_RATE 16 + +/** + * \brief Rate of absorption and squeezing for DrySPONGE256. + */ +#define DRYSPONGE256_RATE 16 + +/** + * \brief Size of the "x" value for DrySPONGE128. + */ +#define DRYSPONGE128_XSIZE 16 + +/** + * \brief Size of the "x" value for DrySPONGE256. + */ +#define DRYSPONGE256_XSIZE 16 + +/** + * \brief Normal number of rounds for DrySPONGE128 when absorbing + * and squeezing data. + */ +#define DRYSPONGE128_ROUNDS 7 + +/** + * \brief Number of rounds for DrySPONGE128 during initialization. + */ +#define DRYSPONGE128_INIT_ROUNDS 11 + +/** + * \brief Normal number of rounds for DrySPONGE256 when absorbing + * and squeezing data. + */ +#define DRYSPONGE256_ROUNDS 8 + +/** + * \brief Number of rounds for DrySPONGE256 during initialization. + */ +#define DRYSPONGE256_INIT_ROUNDS 12 + +/** + * \brief DrySPONGE128 domain bit for a padded block. + */ +#define DRYDOMAIN128_PADDED (1 << 8) + +/** + * \brief DrySPONGE128 domain bit for a final block. + */ +#define DRYDOMAIN128_FINAL (1 << 9) + +/** + * \brief DrySPONGE128 domain value for processing the nonce. + */ +#define DRYDOMAIN128_NONCE (1 << 10) + +/** + * \brief DrySPONGE128 domain value for processing the associated data. + */ +#define DRYDOMAIN128_ASSOC_DATA (2 << 10) + +/** + * \brief DrySPONGE128 domain value for processing the message. + */ +#define DRYDOMAIN128_MESSAGE (3 << 10) + +/** + * \brief DrySPONGE256 domain bit for a padded block. + */ +#define DRYDOMAIN256_PADDED (1 << 2) + +/** + * \brief DrySPONGE256 domain bit for a final block. + */ +#define DRYDOMAIN256_FINAL (1 << 3) + +/** + * \brief DrySPONGE256 domain value for processing the nonce. + */ +#define DRYDOMAIN256_NONCE (1 << 4) + +/** + * \brief DrySPONGE256 domain value for processing the associated data. + */ +#define DRYDOMAIN256_ASSOC_DATA (2 << 4) + +/** + * \brief DrySPONGE256 domain value for processing the message. + */ +#define DRYDOMAIN256_MESSAGE (3 << 4) + +/** + * \brief Internal state of the GASCON-128 permutation. + */ +typedef union +{ + uint64_t S[GASCON128_STATE_SIZE / 8]; /**< 64-bit words of the state */ + uint32_t W[GASCON128_STATE_SIZE / 4]; /**< 32-bit words of the state */ + uint8_t B[GASCON128_STATE_SIZE]; /**< Bytes of the state */ + +} gascon128_state_t; + +/** + * \brief Internal state of the GASCON-256 permutation. + */ +typedef union +{ + uint64_t S[GASCON256_STATE_SIZE / 8]; /**< 64-bit words of the state */ + uint32_t W[GASCON256_STATE_SIZE / 4]; /**< 32-bit words of the state */ + uint8_t B[GASCON256_STATE_SIZE]; /**< Bytes of the state */ + +} gascon256_state_t; + +/** + * \brief Structure of a rate block for DrySPONGE128. + */ +typedef union +{ + uint64_t S[DRYSPONGE128_RATE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE128_RATE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE128_RATE]; /**< Bytes of the rate */ + +} drysponge128_rate_t; + +/** + * \brief Structure of a rate block for DrySPONGE256. + */ +typedef union +{ + uint64_t S[DRYSPONGE256_RATE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE256_RATE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE256_RATE]; /**< Bytes of the rate */ + +} drysponge256_rate_t; + +/** + * \brief Structure of the "x" value for DrySPONGE128. + */ +typedef union +{ + uint64_t S[DRYSPONGE128_XSIZE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE128_XSIZE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE128_XSIZE]; /**< Bytes of the rate */ + +} drysponge128_x_t; + +/** + * \brief Structure of the "x" value for DrySPONGE256. + */ +typedef union +{ + uint64_t S[DRYSPONGE256_XSIZE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE256_XSIZE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE256_XSIZE]; /**< Bytes of the rate */ + +} drysponge256_x_t; + +/** + * \brief Structure of the rolling DrySPONGE128 state. + */ +typedef struct +{ + gascon128_state_t c; /**< GASCON-128 state for the capacity */ + drysponge128_rate_t r; /**< Buffer for a rate block of data */ + drysponge128_x_t x; /**< "x" value for the sponge */ + uint32_t domain; /**< Domain value to mix on next F call */ + uint32_t rounds; /**< Number of rounds for next G call */ + +} drysponge128_state_t; + +/** + * \brief Structure of the rolling DrySPONGE256 state. + */ +typedef struct +{ + gascon256_state_t c; /**< GASCON-256 state for the capacity */ + drysponge256_rate_t r; /**< Buffer for a rate block of data */ + drysponge256_x_t x; /**< "x" value for the sponge */ + uint32_t domain; /**< Domain value to mix on next F call */ + uint32_t rounds; /**< Number of rounds for next G call */ + +} drysponge256_state_t; + +/** + * \brief Permutes the GASCON-128 state using one iteration of CoreRound. + * + * \param state The GASCON-128 state to be permuted. + * \param round The round number. + * + * The input and output \a state will be in little-endian byte order. + */ +void gascon128_core_round(gascon128_state_t *state, uint8_t round); + +/** + * \brief Permutes the GASCON-256 state using one iteration of CoreRound. + * + * \param state The GASCON-256 state to be permuted. + * \param round The round number. + * + * The input and output \a state will be in little-endian byte order. + */ +void gascon256_core_round(gascon256_state_t *state, uint8_t round); + +/** + * \brief Performs the DrySPONGE128 G function which runs the core + * rounds and squeezes data out of the GASGON-128 state. + * + * \param state The DrySPONGE128 state. + * + * The data that is squeezed out will be in state->r on exit. + */ +void drysponge128_g(drysponge128_state_t *state); + +/** + * \brief Performs the DrySPONGE256 G function which runs the core + * rounds and squeezes data out of the GASGON-256 state. + * + * \param state The DrySPONGE256 state. + * + * The data that is squeezed out will be in state->r on exit. + */ +void drysponge256_g(drysponge256_state_t *state); + +/** + * \brief Performs the DrySPONGE128 G function which runs the core + * rounds but does not squeeze out any output. + * + * \param state The DrySPONGE128 state. + */ +void drysponge128_g_core(drysponge128_state_t *state); + +/** + * \brief Performs the DrySPONGE256 G function which runs the core + * rounds but does not squeeze out any output. + * + * \param state The DrySPONGE256 state. + */ +void drysponge256_g_core(drysponge256_state_t *state); + +/** + * \brief Performs the absorption phase of the DrySPONGE128 F function. + * + * \param state The DrySPONGE128 state. + * \param input The block of input data to incorporate into the state. + * \param len The length of the input block, which must be less than + * or equal to DRYSPONGE128_RATE. Smaller input blocks will be padded. + * + * This function must be followed by a call to drysponge128_g() or + * drysponge128_g_core() to perform the full F operation. + */ +void drysponge128_f_absorb + (drysponge128_state_t *state, const unsigned char *input, unsigned len); + +/** + * \brief Performs the absorption phase of the DrySPONGE256 F function. + * + * \param state The DrySPONGE256 state. + * \param input The block of input data to incorporate into the state. + * \param len The length of the input block, which must be less than + * or equal to DRYSPONGE256_RATE. Smaller input blocks will be padded. + * + * This function must be followed by a call to drysponge256_g() or + * drysponge256_g_core() to perform the full F operation. + */ +void drysponge256_f_absorb + (drysponge256_state_t *state, const unsigned char *input, unsigned len); + +/** + * \brief Set up a DrySPONGE128 state to begin encryption or decryption. + * + * \param state The DrySPONGE128 state. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the 16 bytes of the nonce. + * \param final_block Non-zero if after key setup there will be no more blocks. + */ +void drysponge128_setup + (drysponge128_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block); + +/** + * \brief Set up a DrySPONGE256 state to begin encryption or decryption. + * + * \param state The DrySPONGE256 state. + * \param key Points to the 32 bytes of the key. + * \param nonce Points to the 16 bytes of the nonce. + * \param final_block Non-zero if after key setup there will be no more blocks. + */ +void drysponge256_setup + (drysponge256_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-util.h b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon128/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.c b/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.h b/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/api.h b/drygascon/Implementations/crypto_aead/drygascon256/rhys/api.h new file mode 100644 index 0000000..75fabd7 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 32 +#define CRYPTO_NOOVERLAP 1 diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.c b/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.c new file mode 100644 index 0000000..e963903 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.c @@ -0,0 +1,421 @@ +/* + * 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 "drygascon.h" +#include "internal-drysponge.h" +#include + +aead_cipher_t const drygascon128_cipher = { + "DryGASCON128", + DRYGASCON128_KEY_SIZE, + DRYGASCON128_NONCE_SIZE, + DRYGASCON128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon128_aead_encrypt, + drygascon128_aead_decrypt +}; + +aead_cipher_t const drygascon256_cipher = { + "DryGASCON256", + DRYGASCON256_KEY_SIZE, + DRYGASCON256_NONCE_SIZE, + DRYGASCON256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon256_aead_encrypt, + drygascon256_aead_decrypt +}; + +aead_hash_algorithm_t const drygascon128_hash_algorithm = { + "DryGASCON128-HASH", + sizeof(int), + DRYGASCON128_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon128_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 drygascon256_hash_algorithm = { + "DryGASCON256-HASH", + sizeof(int), + DRYGASCON256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + drygascon256_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 Processes associated data for DryGASCON128. + * + * \param state DrySPONGE128 sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must not be zero. + * \param finalize Non-zero to finalize packet processing because + * the message is zero-length. + */ +static void drygascon128_process_ad + (drysponge128_state_t *state, const unsigned char *ad, + unsigned long long adlen, int finalize) +{ + /* Process all blocks except the last one */ + while (adlen > DRYSPONGE128_RATE) { + drysponge128_f_absorb(state, ad, DRYSPONGE128_RATE); + drysponge128_g_core(state); + ad += DRYSPONGE128_RATE; + adlen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state->domain = DRYDOMAIN128_ASSOC_DATA; + if (finalize) + state->domain |= DRYDOMAIN128_FINAL; + if (adlen < DRYSPONGE128_RATE) + state->domain |= DRYDOMAIN128_PADDED; + drysponge128_f_absorb(state, ad, (unsigned)adlen); + drysponge128_g(state); +} + +/** + * \brief Processes associated data for DryGASCON256. + * + * \param state DrySPONGE256 sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must not be zero. + * \param finalize Non-zero to finalize packet processing because + * the message is zero-length. + */ +static void drygascon256_process_ad + (drysponge256_state_t *state, const unsigned char *ad, + unsigned long long adlen, int finalize) +{ + /* Process all blocks except the last one */ + while (adlen > DRYSPONGE256_RATE) { + drysponge256_f_absorb(state, ad, DRYSPONGE256_RATE); + drysponge256_g_core(state); + ad += DRYSPONGE256_RATE; + adlen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state->domain = DRYDOMAIN256_ASSOC_DATA; + if (finalize) + state->domain |= DRYDOMAIN256_FINAL; + if (adlen < DRYSPONGE256_RATE) + state->domain |= DRYDOMAIN256_PADDED; + drysponge256_f_absorb(state, ad, (unsigned)adlen); + drysponge256_g(state); +} + +int drygascon128_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) +{ + drysponge128_state_t state; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DRYGASCON128_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + drysponge128_setup(&state, k, npub, adlen == 0 && mlen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon128_process_ad(&state, ad, adlen, mlen == 0); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + /* Processs all blocks except the last one */ + while (mlen > DRYSPONGE128_RATE) { + drysponge128_f_absorb(&state, m, DRYSPONGE128_RATE); + lw_xor_block_2_src(c, m, state.r.B, DRYSPONGE128_RATE); + drysponge128_g(&state); + c += DRYSPONGE128_RATE; + m += DRYSPONGE128_RATE; + mlen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN128_MESSAGE | DRYDOMAIN128_FINAL; + if (mlen < DRYSPONGE128_RATE) + state.domain |= DRYDOMAIN128_PADDED; + temp = (unsigned)mlen; + drysponge128_f_absorb(&state, m, temp); + lw_xor_block_2_src(c, m, state.r.B, temp); + drysponge128_g(&state); + c += temp; + } + + /* Generate the authentication tag */ + memcpy(c, state.r.B, DRYGASCON128_TAG_SIZE); + return 0; +} + +int drygascon128_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) +{ + drysponge128_state_t state; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DRYGASCON128_TAG_SIZE) + return -1; + *mlen = clen - DRYGASCON128_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + clen -= DRYGASCON128_TAG_SIZE; + drysponge128_setup(&state, k, npub, adlen == 0 && clen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon128_process_ad(&state, ad, adlen, clen == 0); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + /* Processs all blocks except the last one */ + while (clen > DRYSPONGE128_RATE) { + lw_xor_block_2_src(m, c, state.r.B, DRYSPONGE128_RATE); + drysponge128_f_absorb(&state, m, DRYSPONGE128_RATE); + drysponge128_g(&state); + c += DRYSPONGE128_RATE; + m += DRYSPONGE128_RATE; + clen -= DRYSPONGE128_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN128_MESSAGE | DRYDOMAIN128_FINAL; + if (clen < DRYSPONGE128_RATE) + state.domain |= DRYDOMAIN128_PADDED; + temp = (unsigned)clen; + lw_xor_block_2_src(m, c, state.r.B, temp); + drysponge128_f_absorb(&state, m, temp); + drysponge128_g(&state); + c += temp; + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state.r.B, c, DRYGASCON128_TAG_SIZE); +} + +int drygascon256_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) +{ + drysponge256_state_t state; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DRYGASCON256_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + drysponge256_setup(&state, k, npub, adlen == 0 && mlen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon256_process_ad(&state, ad, adlen, mlen == 0); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + /* Processs all blocks except the last one */ + while (mlen > DRYSPONGE256_RATE) { + drysponge256_f_absorb(&state, m, DRYSPONGE256_RATE); + lw_xor_block_2_src(c, m, state.r.B, DRYSPONGE256_RATE); + drysponge256_g(&state); + c += DRYSPONGE256_RATE; + m += DRYSPONGE256_RATE; + mlen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN256_MESSAGE | DRYDOMAIN256_FINAL; + if (mlen < DRYSPONGE256_RATE) + state.domain |= DRYDOMAIN256_PADDED; + temp = (unsigned)mlen; + drysponge256_f_absorb(&state, m, temp); + lw_xor_block_2_src(c, m, state.r.B, temp); + drysponge256_g(&state); + c += temp; + } + + /* Generate the authentication tag */ + memcpy(c, state.r.B, 16); + drysponge256_g(&state); + memcpy(c + 16, state.r.B, 16); + return 0; +} + +int drygascon256_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) +{ + drysponge256_state_t state; + unsigned char *mtemp = m; + unsigned temp; + int result; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DRYGASCON256_TAG_SIZE) + return -1; + *mlen = clen - DRYGASCON256_TAG_SIZE; + + /* Initialize the sponge state with the key and nonce */ + clen -= DRYGASCON256_TAG_SIZE; + drysponge256_setup(&state, k, npub, adlen == 0 && clen == 0); + + /* Process the associated data */ + if (adlen > 0) + drygascon256_process_ad(&state, ad, adlen, clen == 0); + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + /* Processs all blocks except the last one */ + while (clen > DRYSPONGE256_RATE) { + lw_xor_block_2_src(m, c, state.r.B, DRYSPONGE256_RATE); + drysponge256_f_absorb(&state, m, DRYSPONGE256_RATE); + drysponge256_g(&state); + c += DRYSPONGE256_RATE; + m += DRYSPONGE256_RATE; + clen -= DRYSPONGE256_RATE; + } + + /* Process the last block with domain separation and padding */ + state.domain = DRYDOMAIN256_MESSAGE | DRYDOMAIN256_FINAL; + if (clen < DRYSPONGE256_RATE) + state.domain |= DRYDOMAIN256_PADDED; + temp = (unsigned)clen; + lw_xor_block_2_src(m, c, state.r.B, temp); + drysponge256_f_absorb(&state, m, temp); + drysponge256_g(&state); + c += temp; + } + + /* Check the authentication tag which is split into two pieces */ + result = aead_check_tag(0, 0, state.r.B, c, 16); + drysponge256_g(&state); + return aead_check_tag_precheck + (mtemp, *mlen, state.r.B, c + 16, 16, ~result); +} + +/** + * \brief Precomputed initialization vector for DryGASCON128-HASH. + * + * This is the CST_H value from the DryGASCON specification after it + * has been processed by the key setup function for DrySPONGE128. + */ +static unsigned char const drygascon128_hash_init[] = { + /* c */ + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + /* x */ + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89 +}; + +int drygascon128_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + drysponge128_state_t state; + memcpy(state.c.B, drygascon128_hash_init, sizeof(state.c.B)); + memcpy(state.x.B, drygascon128_hash_init + sizeof(state.c.B), + sizeof(state.x.B)); + state.domain = 0; + state.rounds = DRYSPONGE128_ROUNDS; + drygascon128_process_ad(&state, in, inlen, 1); + memcpy(out, state.r.B, 16); + drysponge128_g(&state); + memcpy(out + 16, state.r.B, 16); + return 0; +} + +/** + * \brief Precomputed initialization vector for DryGASCON256-HASH. + * + * This is the CST_H value from the DryGASCON specification after it + * has been processed by the key setup function for DrySPONGE256. + */ +static unsigned char const drygascon256_hash_init[] = { + /* c */ + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + 0x13, 0x19, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x44, + 0xa4, 0x09, 0x38, 0x22, 0x29, 0x9f, 0x31, 0xd0, + 0x08, 0x2e, 0xfa, 0x98, 0xec, 0x4e, 0x6c, 0x89, + 0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 0xd3, + /* x */ + 0x45, 0x28, 0x21, 0xe6, 0x38, 0xd0, 0x13, 0x77, + 0xbe, 0x54, 0x66, 0xcf, 0x34, 0xe9, 0x0c, 0x6c +}; + +int drygascon256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + drysponge256_state_t state; + memcpy(state.c.B, drygascon256_hash_init, sizeof(state.c.B)); + memcpy(state.x.B, drygascon256_hash_init + sizeof(state.c.B), + sizeof(state.x.B)); + state.domain = 0; + state.rounds = DRYSPONGE256_ROUNDS; + drygascon256_process_ad(&state, in, inlen, 1); + memcpy(out, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 16, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 32, state.r.B, 16); + drysponge256_g(&state); + memcpy(out + 48, state.r.B, 16); + return 0; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.h b/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.h new file mode 100644 index 0000000..12e18c3 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/drygascon.h @@ -0,0 +1,264 @@ +/* + * 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_DRYGASCON_H +#define LWCRYPTO_DRYGASCON_H + +#include "aead-common.h" + +/** + * \file drygascon.h + * \brief DryGASCON authenticated encryption algorithm. + * + * DryGASCON is a family of authenticated encryption algorithms based + * around a generalised version of the ASCON permutation. DryGASCON + * is designed to provide some protection against power analysis. + * + * There are four algorithms in the DryGASCON family: + * + * \li DryGASCON128 is an authenticated encryption algorithm with a + * 128-bit key, a 128-bit nonce, and a 128-bit authentication tag. + * \li DryGASCON256 is an authenticated encryption algorithm with a + * 256-bit key, a 128-bit nonce, and a 128-256 authentication tag. + * \li DryGASCON128-HASH is a hash algorithm with a 256-bit output. + * \li DryGASCON256-HASH is a hash algorithm with a 512-bit output. + * + * DryGASCON128 and DryGASCON128-HASH are the primary members of the family. + * + * References: https://github.com/sebastien-riou/DryGASCON + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for DryGASCON128. + */ +#define DRYGASCON128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for DryGASCON128. + */ +#define DRYGASCON128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for DryGASCON128. + */ +#define DRYGASCON128_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for DryGASCON128-HASH. + */ +#define DRYGASCON128_HASH_SIZE 32 + +/** + * \brief Size of the key for DryGASCON256. + */ +#define DRYGASCON256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for DryGASCON256. + */ +#define DRYGASCON256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for DryGASCON256. + */ +#define DRYGASCON256_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for DryGASCON256-HASH. + */ +#define DRYGASCON256_HASH_SIZE 64 + +/** + * \brief Meta-information block for the DryGASCON128 cipher. + */ +extern aead_cipher_t const drygascon128_cipher; + +/** + * \brief Meta-information block for the DryGASCON256 cipher. + */ +extern aead_cipher_t const drygascon256_cipher; + +/** + * \brief Meta-information block for DryGASCON128-HASH. + */ +extern aead_hash_algorithm_t const drygascon128_hash_algorithm; + +/** + * \brief Meta-information block for DryGASCON256-HASH. + */ +extern aead_hash_algorithm_t const drygascon256_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with DryGASCON128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa drygascon128_aead_decrypt() + */ +int drygascon128_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); + +/** + * \brief Decrypts and authenticates a packet with DryGASCON128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa drygascon128_aead_encrypt() + */ +int drygascon128_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); + +/** + * \brief Encrypts and authenticates a packet with DryGASCON256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa drygascon256_aead_decrypt() + */ +int drygascon256_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); + +/** + * \brief Decrypts and authenticates a packet with DryGASCON256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa drygascon256_aead_encrypt() + */ +int drygascon256_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); + +/** + * \brief Hashes a block of input data with DRYGASCON128. + * + * \param out Buffer to receive the hash output which must be at least + * DRYGASCON128_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 drygascon128_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with DRYGASCON256. + * + * \param out Buffer to receive the hash output which must be at least + * DRYGASCON256_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 drygascon256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/encrypt.c b/drygascon/Implementations/crypto_aead/drygascon256/rhys/encrypt.c new file mode 100644 index 0000000..9f3c373 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "drygascon.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 drygascon256_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 drygascon256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.c b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.c new file mode 100644 index 0000000..67f1b27 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.c @@ -0,0 +1,600 @@ +/* + * 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 "internal-drysponge.h" +#include + +/* Right rotations in bit-interleaved format */ +#define intRightRotateEven(x,bits) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate(_x0, (bits)); \ + _x1 = rightRotate(_x1, (bits)); \ + _x0 | (((uint64_t)_x1) << 32); \ + })) +#define intRightRotateOdd(x,bits) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate(_x0, ((bits) + 1) % 32); \ + _x1 = rightRotate(_x1, (bits)); \ + _x1 | (((uint64_t)_x0) << 32); \ + })) +#define intRightRotate1_64(x) \ + (__extension__ ({ \ + uint32_t _x0 = (uint32_t)(x); \ + uint32_t _x1 = (uint32_t)((x) >> 32); \ + _x0 = rightRotate1(_x0); \ + _x1 | (((uint64_t)_x0) << 32); \ + })) +#define intRightRotate2_64(x) (intRightRotateEven((x), 1)) +#define intRightRotate3_64(x) (intRightRotateOdd((x), 1)) +#define intRightRotate4_64(x) (intRightRotateEven((x), 2)) +#define intRightRotate5_64(x) (intRightRotateOdd((x), 2)) +#define intRightRotate6_64(x) (intRightRotateEven((x), 3)) +#define intRightRotate7_64(x) (intRightRotateOdd((x), 3)) +#define intRightRotate8_64(x) (intRightRotateEven((x), 4)) +#define intRightRotate9_64(x) (intRightRotateOdd((x), 4)) +#define intRightRotate10_64(x) (intRightRotateEven((x), 5)) +#define intRightRotate11_64(x) (intRightRotateOdd((x), 5)) +#define intRightRotate12_64(x) (intRightRotateEven((x), 6)) +#define intRightRotate13_64(x) (intRightRotateOdd((x), 6)) +#define intRightRotate14_64(x) (intRightRotateEven((x), 7)) +#define intRightRotate15_64(x) (intRightRotateOdd((x), 7)) +#define intRightRotate16_64(x) (intRightRotateEven((x), 8)) +#define intRightRotate17_64(x) (intRightRotateOdd((x), 8)) +#define intRightRotate18_64(x) (intRightRotateEven((x), 9)) +#define intRightRotate19_64(x) (intRightRotateOdd((x), 9)) +#define intRightRotate20_64(x) (intRightRotateEven((x), 10)) +#define intRightRotate21_64(x) (intRightRotateOdd((x), 10)) +#define intRightRotate22_64(x) (intRightRotateEven((x), 11)) +#define intRightRotate23_64(x) (intRightRotateOdd((x), 11)) +#define intRightRotate24_64(x) (intRightRotateEven((x), 12)) +#define intRightRotate25_64(x) (intRightRotateOdd((x), 12)) +#define intRightRotate26_64(x) (intRightRotateEven((x), 13)) +#define intRightRotate27_64(x) (intRightRotateOdd((x), 13)) +#define intRightRotate28_64(x) (intRightRotateEven((x), 14)) +#define intRightRotate29_64(x) (intRightRotateOdd((x), 14)) +#define intRightRotate30_64(x) (intRightRotateEven((x), 15)) +#define intRightRotate31_64(x) (intRightRotateOdd((x), 15)) +#define intRightRotate32_64(x) (intRightRotateEven((x), 16)) +#define intRightRotate33_64(x) (intRightRotateOdd((x), 16)) +#define intRightRotate34_64(x) (intRightRotateEven((x), 17)) +#define intRightRotate35_64(x) (intRightRotateOdd((x), 17)) +#define intRightRotate36_64(x) (intRightRotateEven((x), 18)) +#define intRightRotate37_64(x) (intRightRotateOdd((x), 18)) +#define intRightRotate38_64(x) (intRightRotateEven((x), 19)) +#define intRightRotate39_64(x) (intRightRotateOdd((x), 19)) +#define intRightRotate40_64(x) (intRightRotateEven((x), 20)) +#define intRightRotate41_64(x) (intRightRotateOdd((x), 20)) +#define intRightRotate42_64(x) (intRightRotateEven((x), 21)) +#define intRightRotate43_64(x) (intRightRotateOdd((x), 21)) +#define intRightRotate44_64(x) (intRightRotateEven((x), 22)) +#define intRightRotate45_64(x) (intRightRotateOdd((x), 22)) +#define intRightRotate46_64(x) (intRightRotateEven((x), 23)) +#define intRightRotate47_64(x) (intRightRotateOdd((x), 23)) +#define intRightRotate48_64(x) (intRightRotateEven((x), 24)) +#define intRightRotate49_64(x) (intRightRotateOdd((x), 24)) +#define intRightRotate50_64(x) (intRightRotateEven((x), 25)) +#define intRightRotate51_64(x) (intRightRotateOdd((x), 25)) +#define intRightRotate52_64(x) (intRightRotateEven((x), 26)) +#define intRightRotate53_64(x) (intRightRotateOdd((x), 26)) +#define intRightRotate54_64(x) (intRightRotateEven((x), 27)) +#define intRightRotate55_64(x) (intRightRotateOdd((x), 27)) +#define intRightRotate56_64(x) (intRightRotateEven((x), 28)) +#define intRightRotate57_64(x) (intRightRotateOdd((x), 28)) +#define intRightRotate58_64(x) (intRightRotateEven((x), 29)) +#define intRightRotate59_64(x) (intRightRotateOdd((x), 29)) +#define intRightRotate60_64(x) (intRightRotateEven((x), 30)) +#define intRightRotate61_64(x) (intRightRotateOdd((x), 30)) +#define intRightRotate62_64(x) (intRightRotateEven((x), 31)) +#define intRightRotate63_64(x) (intRightRotateOdd((x), 31)) + +void gascon128_core_round(gascon128_state_t *state, uint8_t round) +{ + uint64_t t0, t1, t2, t3, t4; + + /* Load the state into local varaibles */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); +#endif + + /* Add the round constant to the middle of the state */ + x2 ^= ((0x0F - round) << 4) | round; + + /* Substitution layer */ + x0 ^= x4; x2 ^= x1; x4 ^= x3; t0 = (~x0) & x1; t1 = (~x1) & x2; + t2 = (~x2) & x3; t3 = (~x3) & x4; t4 = (~x4) & x0; x0 ^= t1; + x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; x1 ^= x0; x3 ^= x2; + x0 ^= x4; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= intRightRotate19_64(x0) ^ intRightRotate28_64(x0); + x1 ^= intRightRotate61_64(x1) ^ intRightRotate38_64(x1); + x2 ^= intRightRotate1_64(x2) ^ intRightRotate6_64(x2); + x3 ^= intRightRotate10_64(x3) ^ intRightRotate17_64(x3); + x4 ^= intRightRotate7_64(x4) ^ intRightRotate40_64(x4); + + /* Write the local variables back to the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); +#endif +} + +void gascon256_core_round(gascon256_state_t *state, uint8_t round) +{ + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + + /* Load the state into local varaibles */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; + uint64_t x8 = state->S[8]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); + uint64_t x8 = le_load_word64(state->B + 64); +#endif + + /* Add the round constant to the middle of the state */ + x4 ^= ((0x0F - round) << 4) | round; + + /* Substitution layer */ + x0 ^= x8; x2 ^= x1; x4 ^= x3; x6 ^= x5; x8 ^= x7; t0 = (~x0) & x1; + t1 = (~x1) & x2; t2 = (~x2) & x3; t3 = (~x3) & x4; t4 = (~x4) & x5; + t5 = (~x5) & x6; t6 = (~x6) & x7; t7 = (~x7) & x8; t8 = (~x8) & x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t5; x5 ^= t6; x6 ^= t7; + x7 ^= t8; x8 ^= t0; x1 ^= x0; x3 ^= x2; x5 ^= x4; x7 ^= x6; x0 ^= x8; + x4 = ~x4; + + /* Linear diffusion layer */ + x0 ^= intRightRotate19_64(x0) ^ intRightRotate28_64(x0); + x1 ^= intRightRotate61_64(x1) ^ intRightRotate38_64(x1); + x2 ^= intRightRotate1_64(x2) ^ intRightRotate6_64(x2); + x3 ^= intRightRotate10_64(x3) ^ intRightRotate17_64(x3); + x4 ^= intRightRotate7_64(x4) ^ intRightRotate40_64(x4); + x5 ^= intRightRotate31_64(x5) ^ intRightRotate26_64(x5); + x6 ^= intRightRotate53_64(x6) ^ intRightRotate58_64(x6); + x7 ^= intRightRotate9_64(x7) ^ intRightRotate46_64(x7); + x8 ^= intRightRotate43_64(x8) ^ intRightRotate50_64(x8); + + /* Write the local variables back to the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; + state->S[8] = x8; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); + le_store_word64(state->B + 64, x8); +#endif +} + +void drysponge128_g(drysponge128_state_t *state) +{ + unsigned round; + + /* Perform the first round. For each round we XOR the 16 bytes of + * the output data with the first 16 bytes of the state. And then + * XOR with the next 16 bytes of the state, rotated by 4 bytes */ + gascon128_core_round(&(state->c), 0); + state->r.W[0] = state->c.W[0] ^ state->c.W[5]; + state->r.W[1] = state->c.W[1] ^ state->c.W[6]; + state->r.W[2] = state->c.W[2] ^ state->c.W[7]; + state->r.W[3] = state->c.W[3] ^ state->c.W[4]; + + /* Perform the rest of the rounds */ + for (round = 1; round < state->rounds; ++round) { + gascon128_core_round(&(state->c), round); + state->r.W[0] ^= state->c.W[0] ^ state->c.W[5]; + state->r.W[1] ^= state->c.W[1] ^ state->c.W[6]; + state->r.W[2] ^= state->c.W[2] ^ state->c.W[7]; + state->r.W[3] ^= state->c.W[3] ^ state->c.W[4]; + } +} + +void drysponge256_g(drysponge256_state_t *state) +{ + unsigned round; + + /* Perform the first round. For each round we XOR the 16 bytes of + * the output data with the first 16 bytes of the state. And then + * XOR with the next 16 bytes of the state, rotated by 4 bytes. + * And so on for a total of 64 bytes XOR'ed into the output data. */ + gascon256_core_round(&(state->c), 0); + state->r.W[0] = state->c.W[0] ^ state->c.W[5] ^ + state->c.W[10] ^ state->c.W[15]; + state->r.W[1] = state->c.W[1] ^ state->c.W[6] ^ + state->c.W[11] ^ state->c.W[12]; + state->r.W[2] = state->c.W[2] ^ state->c.W[7] ^ + state->c.W[8] ^ state->c.W[13]; + state->r.W[3] = state->c.W[3] ^ state->c.W[4] ^ + state->c.W[9] ^ state->c.W[14]; + + /* Perform the rest of the rounds */ + for (round = 1; round < state->rounds; ++round) { + gascon256_core_round(&(state->c), round); + state->r.W[0] ^= state->c.W[0] ^ state->c.W[5] ^ + state->c.W[10] ^ state->c.W[15]; + state->r.W[1] ^= state->c.W[1] ^ state->c.W[6] ^ + state->c.W[11] ^ state->c.W[12]; + state->r.W[2] ^= state->c.W[2] ^ state->c.W[7] ^ + state->c.W[8] ^ state->c.W[13]; + state->r.W[3] ^= state->c.W[3] ^ state->c.W[4] ^ + state->c.W[9] ^ state->c.W[14]; + } +} + +void drysponge128_g_core(drysponge128_state_t *state) +{ + unsigned round; + for (round = 0; round < state->rounds; ++round) + gascon128_core_round(&(state->c), round); +} + +void drysponge256_g_core(drysponge256_state_t *state) +{ + unsigned round; + for (round = 0; round < state->rounds; ++round) + gascon256_core_round(&(state->c), round); +} + +/** + * \brief Selects an element of x in constant time. + * + * \param x Points to the four elements of x. + * \param index Index of which element to extract between 0 and 3. + * + * \return The selected element of x. + */ +STATIC_INLINE uint32_t drysponge_select_x(const uint32_t x[4], uint8_t index) +{ + /* We need to be careful how we select each element of x because + * we are doing a data-dependent fetch here. Do the fetch in a way + * that should avoid cache timing issues by fetching every element + * of x and masking away the ones we don't want. + * + * There is a possible side channel here with respect to power analysis. + * The "mask" value will be all-ones for the selected index and all-zeroes + * for the other indexes. This may show up as different power consumption + * for the "result ^= x[i] & mask" statement when i is the selected index. + * Such a side channel could in theory allow reading the plaintext input + * to the cipher by analysing the CPU's power consumption. + * + * The DryGASCON specification acknowledges the possibility of plaintext + * recovery in section 7.4. For software mitigation the specification + * suggests randomization of the indexes into c and x and randomization + * of the order of processing words. We aren't doing that here yet. + * Patches welcome to fix this. + */ + uint32_t mask = -((uint32_t)((0x04 - index) >> 2)); + uint32_t result = x[0] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x01)) >> 2)); + result ^= x[1] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x02)) >> 2)); + result ^= x[2] & mask; + mask = -((uint32_t)((0x04 - (index ^ 0x03)) >> 2)); + return result ^ (x[3] & mask); +} + +/** + * \brief Mixes a 32-bit value into the DrySPONGE128 state. + * + * \param state DrySPONGE128 state. + * \param data The data to be mixed in the bottom 10 bits. + */ +static void drysponge128_mix_phase_round + (drysponge128_state_t *state, uint32_t data) +{ + /* Mix in elements from x according to the 2-bit indexes in the data */ + state->c.W[0] ^= drysponge_select_x(state->x.W, data & 0x03); + state->c.W[2] ^= drysponge_select_x(state->x.W, (data >> 2) & 0x03); + state->c.W[4] ^= drysponge_select_x(state->x.W, (data >> 4) & 0x03); + state->c.W[6] ^= drysponge_select_x(state->x.W, (data >> 6) & 0x03); + state->c.W[8] ^= drysponge_select_x(state->x.W, (data >> 8) & 0x03); +} + +/** + * \brief Mixes a 32-bit value into the DrySPONGE256 state. + * + * \param state DrySPONGE256 state. + * \param data The data to be mixed in the bottom 18 bits. + */ +static void drysponge256_mix_phase_round + (drysponge256_state_t *state, uint32_t data) +{ + /* Mix in elements from x according to the 2-bit indexes in the data */ + state->c.W[0] ^= drysponge_select_x(state->x.W, data & 0x03); + state->c.W[2] ^= drysponge_select_x(state->x.W, (data >> 2) & 0x03); + state->c.W[4] ^= drysponge_select_x(state->x.W, (data >> 4) & 0x03); + state->c.W[6] ^= drysponge_select_x(state->x.W, (data >> 6) & 0x03); + state->c.W[8] ^= drysponge_select_x(state->x.W, (data >> 8) & 0x03); + state->c.W[10] ^= drysponge_select_x(state->x.W, (data >> 10) & 0x03); + state->c.W[12] ^= drysponge_select_x(state->x.W, (data >> 12) & 0x03); + state->c.W[14] ^= drysponge_select_x(state->x.W, (data >> 14) & 0x03); + state->c.W[16] ^= drysponge_select_x(state->x.W, (data >> 16) & 0x03); +} + +/** + * \brief Mixes an input block into a DrySPONGE128 state. + * + * \param state The DrySPONGE128 state. + * \param data Full rate block containing the input data. + */ +static void drysponge128_mix_phase + (drysponge128_state_t *state, const unsigned char data[DRYSPONGE128_RATE]) +{ + /* Mix 10-bit groups into the output, with the domain + * separator added to the last two groups */ + drysponge128_mix_phase_round + (state, data[0] | (((uint32_t)(data[1])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[1] >> 2) | (((uint32_t)(data[2])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[2] >> 4) | (((uint32_t)(data[3])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[3] >> 6) | (((uint32_t)(data[4])) << 2)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, data[5] | (((uint32_t)(data[6])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[6] >> 2) | (((uint32_t)(data[7])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[7] >> 4) | (((uint32_t)(data[8])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[8] >> 6) | (((uint32_t)(data[9])) << 2)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, data[10] | (((uint32_t)(data[11])) << 8)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[11] >> 2) | (((uint32_t)(data[12])) << 6)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, (data[12] >> 4) | (((uint32_t)(data[13])) << 4)); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round + (state, ((data[13] >> 6) | (((uint32_t)(data[14])) << 2))); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round(state, data[15] ^ state->domain); + gascon128_core_round(&(state->c), 0); + drysponge128_mix_phase_round(state, state->domain >> 10); + + /* Revert to the default domain separator for the next block */ + state->domain = 0; +} + +/** + * \brief Mixes an input block into a DrySPONGE256 state. + * + * \param state The DrySPONGE256 state. + * \param data Full rate block containing the input data. + */ +static void drysponge256_mix_phase + (drysponge256_state_t *state, const unsigned char data[DRYSPONGE256_RATE]) +{ + /* Mix 18-bit groups into the output, with the domain in the last group */ + drysponge256_mix_phase_round + (state, data[0] | (((uint32_t)(data[1])) << 8) | + (((uint32_t)(data[2])) << 16)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[2] >> 2) | (((uint32_t)(data[3])) << 6) | + (((uint32_t)(data[4])) << 14)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[4] >> 4) | (((uint32_t)(data[5])) << 4) | + (((uint32_t)(data[6])) << 12)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[6] >> 6) | (((uint32_t)(data[7])) << 2) | + (((uint32_t)(data[8])) << 10)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, data[9] | (((uint32_t)(data[10])) << 8) | + (((uint32_t)(data[11])) << 16)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[11] >> 2) | (((uint32_t)(data[12])) << 6) | + (((uint32_t)(data[13])) << 14)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[13] >> 4) | (((uint32_t)(data[14])) << 4) | + (((uint32_t)(data[15])) << 12)); + gascon256_core_round(&(state->c), 0); + drysponge256_mix_phase_round + (state, (data[15] >> 6) ^ state->domain); + + /* Revert to the default domain separator for the next block */ + state->domain = 0; +} + +void drysponge128_f_absorb + (drysponge128_state_t *state, const unsigned char *input, unsigned len) +{ + if (len >= DRYSPONGE128_RATE) { + drysponge128_mix_phase(state, input); + } else { + unsigned char padded[DRYSPONGE128_RATE]; + memcpy(padded, input, len); + padded[len] = 0x01; + memset(padded + len + 1, 0, DRYSPONGE128_RATE - len - 1); + drysponge128_mix_phase(state, padded); + } +} + +void drysponge256_f_absorb + (drysponge256_state_t *state, const unsigned char *input, unsigned len) +{ + if (len >= DRYSPONGE256_RATE) { + drysponge256_mix_phase(state, input); + } else { + unsigned char padded[DRYSPONGE256_RATE]; + memcpy(padded, input, len); + padded[len] = 0x01; + memset(padded + len + 1, 0, DRYSPONGE256_RATE - len - 1); + drysponge256_mix_phase(state, padded); + } +} + +/** + * \brief Determine if some of the words of an "x" value are identical. + * + * \param x Points to the "x" buffer to check. + * + * \return Non-zero if some of the words are the same, zero if they are + * distinct from each other. + * + * We try to perform the check in constant time to avoid giving away + * any information about the value of the key. + */ +static int drysponge_x_words_are_same(const uint32_t x[4]) +{ + unsigned i, j; + int result = 0; + for (i = 0; i < 3; ++i) { + for (j = i + 1; j < 4; ++j) { + uint32_t check = x[i] ^ x[j]; + result |= (int)((0x100000000ULL - check) >> 32); + } + } + return result; +} + +void drysponge128_setup + (drysponge128_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block) +{ + /* Fill the GASCON-128 state with repeated copies of the key */ + memcpy(state->c.B, key, 16); + memcpy(state->c.B + 16, key, 16); + memcpy(state->c.B + 32, key, 8); + + /* Generate the "x" value for the state. All four words of "x" + * must be unique because they will be used in drysponge_select_x() + * as stand-ins for the bit pairs 00, 01, 10, and 11. + * + * Run the core block operation over and over until "x" is unique. + * Technically the runtime here is key-dependent and not constant. + * If the input key is randomized, this should only take 1 round + * on average so it is "almost constant time". + */ + do { + gascon128_core_round(&(state->c), 0); + } while (drysponge_x_words_are_same(state->c.W)); + memcpy(state->x.W, state->c.W, sizeof(state->x)); + + /* Replace the generated "x" value in the state with the key prefix */ + memcpy(state->c.W, key, sizeof(state->x)); + + /* Absorb the nonce into the state with an increased number of rounds */ + state->rounds = DRYSPONGE128_INIT_ROUNDS; + state->domain = DRYDOMAIN128_NONCE; + if (final_block) + state->domain |= DRYDOMAIN128_FINAL; + drysponge128_f_absorb(state, nonce, 16); + drysponge128_g(state); + + /* Set up the normal number of rounds for future operations */ + state->rounds = DRYSPONGE128_ROUNDS; +} + +void drysponge256_setup + (drysponge256_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block) +{ + /* Fill the GASCON-256 state with repeated copies of the key */ + memcpy(state->c.B, key, 32); + memcpy(state->c.B + 32, key, 32); + memcpy(state->c.B + 64, key, 8); + + /* Generate the "x" value for the state */ + do { + gascon256_core_round(&(state->c), 0); + } while (drysponge_x_words_are_same(state->c.W)); + memcpy(state->x.W, state->c.W, sizeof(state->x)); + + /* Replace the generated "x" value in the state with the key prefix */ + memcpy(state->c.W, key, sizeof(state->x)); + + /* Absorb the nonce into the state with an increased number of rounds */ + state->rounds = DRYSPONGE256_INIT_ROUNDS; + state->domain = DRYDOMAIN256_NONCE; + if (final_block) + state->domain |= DRYDOMAIN256_FINAL; + drysponge256_f_absorb(state, nonce, 16); + drysponge256_g(state); + + /* Set up the normal number of rounds for future operations */ + state->rounds = DRYSPONGE256_ROUNDS; +} diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.h b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.h new file mode 100644 index 0000000..05b0c16 --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-drysponge.h @@ -0,0 +1,345 @@ +/* + * 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_DRYSPONGE_H +#define LW_INTERNAL_DRYSPONGE_H + +#include "internal-util.h" + +/** + * \file internal-drysponge.h + * \brief Internal implementation of DrySPONGE for the DryGASCON cipher. + * + * References: https://github.com/sebastien-riou/DryGASCON + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the GASCON-128 permutation state in bytes. + */ +#define GASCON128_STATE_SIZE 40 + +/** + * \brief Size of the GASCON-256 permutation state in bytes. + */ +#define GASCON256_STATE_SIZE 72 + +/** + * \brief Rate of absorption and squeezing for DrySPONGE128. + */ +#define DRYSPONGE128_RATE 16 + +/** + * \brief Rate of absorption and squeezing for DrySPONGE256. + */ +#define DRYSPONGE256_RATE 16 + +/** + * \brief Size of the "x" value for DrySPONGE128. + */ +#define DRYSPONGE128_XSIZE 16 + +/** + * \brief Size of the "x" value for DrySPONGE256. + */ +#define DRYSPONGE256_XSIZE 16 + +/** + * \brief Normal number of rounds for DrySPONGE128 when absorbing + * and squeezing data. + */ +#define DRYSPONGE128_ROUNDS 7 + +/** + * \brief Number of rounds for DrySPONGE128 during initialization. + */ +#define DRYSPONGE128_INIT_ROUNDS 11 + +/** + * \brief Normal number of rounds for DrySPONGE256 when absorbing + * and squeezing data. + */ +#define DRYSPONGE256_ROUNDS 8 + +/** + * \brief Number of rounds for DrySPONGE256 during initialization. + */ +#define DRYSPONGE256_INIT_ROUNDS 12 + +/** + * \brief DrySPONGE128 domain bit for a padded block. + */ +#define DRYDOMAIN128_PADDED (1 << 8) + +/** + * \brief DrySPONGE128 domain bit for a final block. + */ +#define DRYDOMAIN128_FINAL (1 << 9) + +/** + * \brief DrySPONGE128 domain value for processing the nonce. + */ +#define DRYDOMAIN128_NONCE (1 << 10) + +/** + * \brief DrySPONGE128 domain value for processing the associated data. + */ +#define DRYDOMAIN128_ASSOC_DATA (2 << 10) + +/** + * \brief DrySPONGE128 domain value for processing the message. + */ +#define DRYDOMAIN128_MESSAGE (3 << 10) + +/** + * \brief DrySPONGE256 domain bit for a padded block. + */ +#define DRYDOMAIN256_PADDED (1 << 2) + +/** + * \brief DrySPONGE256 domain bit for a final block. + */ +#define DRYDOMAIN256_FINAL (1 << 3) + +/** + * \brief DrySPONGE256 domain value for processing the nonce. + */ +#define DRYDOMAIN256_NONCE (1 << 4) + +/** + * \brief DrySPONGE256 domain value for processing the associated data. + */ +#define DRYDOMAIN256_ASSOC_DATA (2 << 4) + +/** + * \brief DrySPONGE256 domain value for processing the message. + */ +#define DRYDOMAIN256_MESSAGE (3 << 4) + +/** + * \brief Internal state of the GASCON-128 permutation. + */ +typedef union +{ + uint64_t S[GASCON128_STATE_SIZE / 8]; /**< 64-bit words of the state */ + uint32_t W[GASCON128_STATE_SIZE / 4]; /**< 32-bit words of the state */ + uint8_t B[GASCON128_STATE_SIZE]; /**< Bytes of the state */ + +} gascon128_state_t; + +/** + * \brief Internal state of the GASCON-256 permutation. + */ +typedef union +{ + uint64_t S[GASCON256_STATE_SIZE / 8]; /**< 64-bit words of the state */ + uint32_t W[GASCON256_STATE_SIZE / 4]; /**< 32-bit words of the state */ + uint8_t B[GASCON256_STATE_SIZE]; /**< Bytes of the state */ + +} gascon256_state_t; + +/** + * \brief Structure of a rate block for DrySPONGE128. + */ +typedef union +{ + uint64_t S[DRYSPONGE128_RATE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE128_RATE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE128_RATE]; /**< Bytes of the rate */ + +} drysponge128_rate_t; + +/** + * \brief Structure of a rate block for DrySPONGE256. + */ +typedef union +{ + uint64_t S[DRYSPONGE256_RATE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE256_RATE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE256_RATE]; /**< Bytes of the rate */ + +} drysponge256_rate_t; + +/** + * \brief Structure of the "x" value for DrySPONGE128. + */ +typedef union +{ + uint64_t S[DRYSPONGE128_XSIZE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE128_XSIZE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE128_XSIZE]; /**< Bytes of the rate */ + +} drysponge128_x_t; + +/** + * \brief Structure of the "x" value for DrySPONGE256. + */ +typedef union +{ + uint64_t S[DRYSPONGE256_XSIZE / 8]; /**< 64-bit words of the rate */ + uint32_t W[DRYSPONGE256_XSIZE / 4]; /**< 32-bit words of the rate */ + uint8_t B[DRYSPONGE256_XSIZE]; /**< Bytes of the rate */ + +} drysponge256_x_t; + +/** + * \brief Structure of the rolling DrySPONGE128 state. + */ +typedef struct +{ + gascon128_state_t c; /**< GASCON-128 state for the capacity */ + drysponge128_rate_t r; /**< Buffer for a rate block of data */ + drysponge128_x_t x; /**< "x" value for the sponge */ + uint32_t domain; /**< Domain value to mix on next F call */ + uint32_t rounds; /**< Number of rounds for next G call */ + +} drysponge128_state_t; + +/** + * \brief Structure of the rolling DrySPONGE256 state. + */ +typedef struct +{ + gascon256_state_t c; /**< GASCON-256 state for the capacity */ + drysponge256_rate_t r; /**< Buffer for a rate block of data */ + drysponge256_x_t x; /**< "x" value for the sponge */ + uint32_t domain; /**< Domain value to mix on next F call */ + uint32_t rounds; /**< Number of rounds for next G call */ + +} drysponge256_state_t; + +/** + * \brief Permutes the GASCON-128 state using one iteration of CoreRound. + * + * \param state The GASCON-128 state to be permuted. + * \param round The round number. + * + * The input and output \a state will be in little-endian byte order. + */ +void gascon128_core_round(gascon128_state_t *state, uint8_t round); + +/** + * \brief Permutes the GASCON-256 state using one iteration of CoreRound. + * + * \param state The GASCON-256 state to be permuted. + * \param round The round number. + * + * The input and output \a state will be in little-endian byte order. + */ +void gascon256_core_round(gascon256_state_t *state, uint8_t round); + +/** + * \brief Performs the DrySPONGE128 G function which runs the core + * rounds and squeezes data out of the GASGON-128 state. + * + * \param state The DrySPONGE128 state. + * + * The data that is squeezed out will be in state->r on exit. + */ +void drysponge128_g(drysponge128_state_t *state); + +/** + * \brief Performs the DrySPONGE256 G function which runs the core + * rounds and squeezes data out of the GASGON-256 state. + * + * \param state The DrySPONGE256 state. + * + * The data that is squeezed out will be in state->r on exit. + */ +void drysponge256_g(drysponge256_state_t *state); + +/** + * \brief Performs the DrySPONGE128 G function which runs the core + * rounds but does not squeeze out any output. + * + * \param state The DrySPONGE128 state. + */ +void drysponge128_g_core(drysponge128_state_t *state); + +/** + * \brief Performs the DrySPONGE256 G function which runs the core + * rounds but does not squeeze out any output. + * + * \param state The DrySPONGE256 state. + */ +void drysponge256_g_core(drysponge256_state_t *state); + +/** + * \brief Performs the absorption phase of the DrySPONGE128 F function. + * + * \param state The DrySPONGE128 state. + * \param input The block of input data to incorporate into the state. + * \param len The length of the input block, which must be less than + * or equal to DRYSPONGE128_RATE. Smaller input blocks will be padded. + * + * This function must be followed by a call to drysponge128_g() or + * drysponge128_g_core() to perform the full F operation. + */ +void drysponge128_f_absorb + (drysponge128_state_t *state, const unsigned char *input, unsigned len); + +/** + * \brief Performs the absorption phase of the DrySPONGE256 F function. + * + * \param state The DrySPONGE256 state. + * \param input The block of input data to incorporate into the state. + * \param len The length of the input block, which must be less than + * or equal to DRYSPONGE256_RATE. Smaller input blocks will be padded. + * + * This function must be followed by a call to drysponge256_g() or + * drysponge256_g_core() to perform the full F operation. + */ +void drysponge256_f_absorb + (drysponge256_state_t *state, const unsigned char *input, unsigned len); + +/** + * \brief Set up a DrySPONGE128 state to begin encryption or decryption. + * + * \param state The DrySPONGE128 state. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the 16 bytes of the nonce. + * \param final_block Non-zero if after key setup there will be no more blocks. + */ +void drysponge128_setup + (drysponge128_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block); + +/** + * \brief Set up a DrySPONGE256 state to begin encryption or decryption. + * + * \param state The DrySPONGE256 state. + * \param key Points to the 32 bytes of the key. + * \param nonce Points to the 16 bytes of the nonce. + * \param final_block Non-zero if after key setup there will be no more blocks. + */ +void drysponge256_setup + (drysponge256_state_t *state, const unsigned char *key, + const unsigned char *nonce, int final_block); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-util.h b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/drygascon/Implementations/crypto_aead/drygascon256/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant160v1/LWC_AEAD_KAT_128_96.txt b/elephant/Implementations/crypto_aead/elephant160v1/LWC_AEAD_KAT_128_96.txt index 0c5a5a2..56639af 100644 --- a/elephant/Implementations/crypto_aead/elephant160v1/LWC_AEAD_KAT_128_96.txt +++ b/elephant/Implementations/crypto_aead/elephant160v1/LWC_AEAD_KAT_128_96.txt @@ -1,7623 +1,7623 @@ -Count = 1 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = -CT = 99AD0D35BBB90AA7 - -Count = 2 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00 -CT = DED044E7EEE9F069 - -Count = 3 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001 -CT = 0CC483162FEAB754 - -Count = 4 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102 -CT = 659D3DEAD70D2ABB - -Count = 5 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203 -CT = 0B61EE7AA5D245EF - -Count = 6 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304 -CT = 916219448C0FD045 - -Count = 7 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405 -CT = 9BACF481DD66D403 - -Count = 8 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506 -CT = FDF4E9397191A319 - -Count = 9 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304050607 -CT = 66D9EE19310BF9AD - -Count = 10 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708 -CT = AE9F9C43A1C1EFC7 - -Count = 11 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506070809 -CT = 45C57404B30FB1B7 - -Count = 12 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A -CT = 8A875FE342003DFC - -Count = 13 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B -CT = 7707887E42F415FA - -Count = 14 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C -CT = 2D881B8AB33B8103 - -Count = 15 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D -CT = D1FBA317B0193457 - -Count = 16 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E -CT = 61BC1A89A444FC65 - -Count = 17 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F -CT = 01C0B1B4276BC596 - -Count = 18 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10 -CT = D5E14C3898B8096C - -Count = 19 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C6546D76A2C45A74 - -Count = 20 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 41C8DF8CEC0BEE0D - -Count = 21 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 013CA534B0F71F22 - -Count = 22 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 3E981A262BEE3450 - -Count = 23 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = E2B9DA22782E4FB3 - -Count = 24 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 7F9D29E4D48E7936 - -Count = 25 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 33CE1CFFADBA0FBD - -Count = 26 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = A5340B87EC01EBF7 - -Count = 27 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 9D53C503D0B9943A - -Count = 28 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = BCAE22FB6B4B0071 - -Count = 29 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = E3F6C5D56FC6B773 - -Count = 30 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75CCE11AB4567088 - -Count = 31 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 51C496EBE32E726D - -Count = 32 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 1BDED7551FA9CA73 - -Count = 33 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 24F760685AC9B843 - -Count = 34 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = -CT = C909DAD7810C416E41 - -Count = 35 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00 -CT = C94EA79E535911948F - -Count = 36 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001 -CT = C99CB359A29812D3B2 - -Count = 37 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102 -CT = C9F5EAE75E60F54E5D - -Count = 38 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203 -CT = C99B1634CE122A2109 - -Count = 39 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304 -CT = C90115C3F03BF7B4A3 - -Count = 40 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405 -CT = C90BDB2E356A9EB0E5 - -Count = 41 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506 -CT = C96D83338DC669C7FF - -Count = 42 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304050607 -CT = C9F6AE34AD86F39D4B - -Count = 43 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708 -CT = C93EE846F716398B21 - -Count = 44 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506070809 -CT = C9D5B2AEB004F7D551 - -Count = 45 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A -CT = C91AF08557F5F8591A - -Count = 46 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B -CT = C9E77052CAF50C711C - -Count = 47 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C -CT = C9BDFFC13E04C3E5E5 - -Count = 48 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D -CT = C9418C79A307E150B1 - -Count = 49 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E -CT = C9F1CBC03D13BC9883 - -Count = 50 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F -CT = C991B76B009093A170 - -Count = 51 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C94596968C2F406D8A - -Count = 52 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C95623B7C2153C3E92 - -Count = 53 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9D1BF05385BF38AEB - -Count = 54 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9914B7F80070F7BC4 - -Count = 55 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9AEEFC0929C1650B6 - -Count = 56 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C972CE0096CFD62B55 - -Count = 57 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9EFEAF35063761DD0 - -Count = 58 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9A3B9C64B1A426B5B - -Count = 59 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C93543D1335BF98F11 - -Count = 60 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C90D241FB76741F0DC - -Count = 61 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C92CD9F84FDCB36497 - -Count = 62 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C973811F61D83ED395 - -Count = 63 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9E5BB3BAE03AE146E - -Count = 64 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9C1B34C5F54D6168B - -Count = 65 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C98BA90DE1A851AE95 - -Count = 66 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9B480BADCED31DCA5 - -Count = 67 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = -CT = C90377F863D1D68B7D47 - -Count = 68 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00 -CT = C90330852A0383DB8789 - -Count = 69 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001 -CT = C903E291EDF242D8C0B4 - -Count = 70 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102 -CT = C9038BC8530EBA3F5D5B - -Count = 71 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203 -CT = C903E534809EC8E0320F - -Count = 72 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304 -CT = C9037F3777A0E13DA7A5 - -Count = 73 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405 -CT = C90375F99A65B054A3E3 - -Count = 74 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506 -CT = C90313A187DD1CA3D4F9 - -Count = 75 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304050607 -CT = C903888C80FD5C398E4D - -Count = 76 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708 -CT = C90340CAF2A7CCF39827 - -Count = 77 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506070809 -CT = C903AB901AE0DE3DC657 - -Count = 78 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A -CT = C90364D231072F324A1C - -Count = 79 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B -CT = C9039952E69A2FC6621A - -Count = 80 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C -CT = C903C3DD756EDE09F6E3 - -Count = 81 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D -CT = C9033FAECDF3DD2B43B7 - -Count = 82 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E -CT = C9038FE9746DC9768B85 - -Count = 83 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F -CT = C903EF95DF504A59B276 - -Count = 84 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9033BB422DCF58A7E8C - -Count = 85 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C90328010392CFF62D94 - -Count = 86 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C903AF9DB168813999ED - -Count = 87 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C903EF69CBD0DDC568C2 - -Count = 88 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C903D0CD74C246DC43B0 - -Count = 89 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9030CECB4C6151C3853 - -Count = 90 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C90391C84700B9BC0ED6 - -Count = 91 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C903DD9B721BC088785D - -Count = 92 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034B61656381339C17 - -Count = 93 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9037306ABE7BD8BE3DA - -Count = 94 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C90352FB4C1F06797791 - -Count = 95 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9030DA3AB3102F4C093 - -Count = 96 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9039B998FFED9640768 - -Count = 97 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C903BF91F80F8E1C058D - -Count = 98 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C903F58BB9B1729BBD93 - -Count = 99 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C903CAA20E8C37FBCFA3 - -Count = 100 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = -CT = C9034AEE97703E68E1AFAD - -Count = 101 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00 -CT = C9034AA9EA39EC3DB15563 - -Count = 102 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001 -CT = C9034A7BFEFE1DFCB2125E - -Count = 103 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102 -CT = C9034A12A740E104558FB1 - -Count = 104 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203 -CT = C9034A7C5B9371768AE0E5 - -Count = 105 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304 -CT = C9034AE658644F5F57754F - -Count = 106 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405 -CT = C9034AEC96898A0E3E7109 - -Count = 107 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506 -CT = C9034A8ACE9432A2C90613 - -Count = 108 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304050607 -CT = C9034A11E39312E2535CA7 - -Count = 109 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708 -CT = C9034AD9A5E14872994ACD - -Count = 110 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506070809 -CT = C9034A32FF090F605714BD - -Count = 111 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A -CT = C9034AFDBD22E8915898F6 - -Count = 112 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B -CT = C9034A003DF57591ACB0F0 - -Count = 113 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C -CT = C9034A5AB2668160632409 - -Count = 114 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D -CT = C9034AA6C1DE1C6341915D - -Count = 115 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A16866782771C596F - -Count = 116 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A76FACCBFF433609C - -Count = 117 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034AA2DB31334BE0AC66 - -Count = 118 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034AB16E107D719CFF7E - -Count = 119 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A36F2A2873F534B07 - -Count = 120 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A7606D83F63AFBA28 - -Count = 121 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A49A2672DF8B6915A - -Count = 122 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A9583A729AB76EAB9 - -Count = 123 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A08A754EF07D6DC3C - -Count = 124 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A44F461F47EE2AAB7 - -Count = 125 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034AD20E768C3F594EFD - -Count = 126 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034AEA69B80803E13130 - -Count = 127 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034ACB945FF0B813A57B - -Count = 128 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A94CCB8DEBC9E1279 - -Count = 129 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A02F69C11670ED582 - -Count = 130 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A26FEEBE03076D767 - -Count = 131 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A6CE4AA5ECCF16F79 - -Count = 132 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A53CD1D6389911D49 - -Count = 133 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = -CT = C9034A2FC5C3528515B7D64B - -Count = 134 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00 -CT = C9034A2F82BE1B5740E72C85 - -Count = 135 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001 -CT = C9034A2F50AADCA681E46BB8 - -Count = 136 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102 -CT = C9034A2F39F3625A7903F657 - -Count = 137 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203 -CT = C9034A2F570FB1CA0BDC9903 - -Count = 138 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304 -CT = C9034A2FCD0C46F422010CA9 - -Count = 139 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405 -CT = C9034A2FC7C2AB31736808EF - -Count = 140 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506 -CT = C9034A2FA19AB689DF9F7FF5 - -Count = 141 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304050607 -CT = C9034A2F3AB7B1A99F052541 - -Count = 142 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708 -CT = C9034A2FF2F1C3F30FCF332B - -Count = 143 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506070809 -CT = C9034A2F19AB2BB41D016D5B - -Count = 144 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A -CT = C9034A2FD6E90053EC0EE110 - -Count = 145 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B -CT = C9034A2F2B69D7CEECFAC916 - -Count = 146 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C -CT = C9034A2F71E6443A1D355DEF - -Count = 147 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F8D95FCA71E17E8BB - -Count = 148 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F3DD245390A4A2089 - -Count = 149 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F5DAEEE048965197A - -Count = 150 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F898F138836B6D580 - -Count = 151 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F9A3A32C60CCA8698 - -Count = 152 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F1DA6803C420532E1 - -Count = 153 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F5D52FA841EF9C3CE - -Count = 154 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F62F6459685E0E8BC - -Count = 155 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2FBED78592D620935F - -Count = 156 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F23F376547A80A5DA - -Count = 157 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F6FA0434F03B4D351 - -Count = 158 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2FF95A5437420F371B - -Count = 159 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2FC13D9AB37EB748D6 - -Count = 160 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2FE0C07D4BC545DC9D - -Count = 161 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2FBF989A65C1C86B9F - -Count = 162 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F29A2BEAA1A58AC64 - -Count = 163 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F0DAAC95B4D20AE81 - -Count = 164 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F47B088E5B1A7169F - -Count = 165 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F78993FD8F4C764AF - -Count = 166 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = -CT = C9034A2F7FC024F47371011925 - -Count = 167 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00 -CT = C9034A2F7F8759BDA12451E3EB - -Count = 168 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001 -CT = C9034A2F7F554D7A50E552A4D6 - -Count = 169 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102 -CT = C9034A2F7F3C14C4AC1DB53939 - -Count = 170 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203 -CT = C9034A2F7F52E8173C6F6A566D - -Count = 171 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304 -CT = C9034A2F7FC8EBE00246B7C3C7 - -Count = 172 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405 -CT = C9034A2F7FC2250DC717DEC781 - -Count = 173 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506 -CT = C9034A2F7FA47D107FBB29B09B - -Count = 174 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304050607 -CT = C9034A2F7F3F50175FFBB3EA2F - -Count = 175 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708 -CT = C9034A2F7FF71665056B79FC45 - -Count = 176 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506070809 -CT = C9034A2F7F1C4C8D4279B7A235 - -Count = 177 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A -CT = C9034A2F7FD30EA6A588B82E7E - -Count = 178 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B -CT = C9034A2F7F2E8E7138884C0678 - -Count = 179 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F7401E2CC79839281 - -Count = 180 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F88725A517AA127D5 - -Count = 181 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F3835E3CF6EFCEFE7 - -Count = 182 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F584948F2EDD3D614 - -Count = 183 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F8C68B57E52001AEE - -Count = 184 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9FDD9430687C49F6 - -Count = 185 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F184126CA26B3FD8F - -Count = 186 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F58B55C727A4F0CA0 - -Count = 187 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F6711E360E15627D2 - -Count = 188 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7FBB302364B2965C31 - -Count = 189 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F2614D0A21E366AB4 - -Count = 190 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F6A47E5B967021C3F - -Count = 191 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7FFCBDF2C126B9F875 - -Count = 192 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7FC4DA3C451A0187B8 - -Count = 193 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7FE527DBBDA1F313F3 - -Count = 194 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7FBA7F3C93A57EA4F1 - -Count = 195 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F2C45185C7EEE630A - -Count = 196 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F084D6FAD299661EF - -Count = 197 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F42572E13D511D9F1 - -Count = 198 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F7D7E992E9071ABC1 - -Count = 199 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = -CT = C9034A2F7F967A2083CD8D969311 - -Count = 200 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00 -CT = C9034A2F7F963D5DCA1FD8C669DF - -Count = 201 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001 -CT = C9034A2F7F96EF490DEE19C52EE2 - -Count = 202 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102 -CT = C9034A2F7F968610B312E122B30D - -Count = 203 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203 -CT = C9034A2F7F96E8EC608293FDDC59 - -Count = 204 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304 -CT = C9034A2F7F9672EF97BCBA2049F3 - -Count = 205 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405 -CT = C9034A2F7F9678217A79EB494DB5 - -Count = 206 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506 -CT = C9034A2F7F961E7967C147BE3AAF - -Count = 207 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304050607 -CT = C9034A2F7F96855460E10724601B - -Count = 208 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708 -CT = C9034A2F7F964D1212BB97EE7671 - -Count = 209 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506070809 -CT = C9034A2F7F96A648FAFC85202801 - -Count = 210 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A -CT = C9034A2F7F96690AD11B742FA44A - -Count = 211 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B -CT = C9034A2F7F96948A068674DB8C4C - -Count = 212 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F96CE059572851418B5 - -Count = 213 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9632762DEF8636ADE1 - -Count = 214 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9682319471926B65D3 - -Count = 215 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F96E24D3F4C11445C20 - -Count = 216 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F96366CC2C0AE9790DA - -Count = 217 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9625D9E38E94EBC3C2 - -Count = 218 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F96A2455174DA2477BB - -Count = 219 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F96E2B12BCC86D88694 - -Count = 220 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F96DD1594DE1DC1ADE6 - -Count = 221 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F96013454DA4E01D605 - -Count = 222 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F969C10A71CE2A1E080 - -Count = 223 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F96D04392079B95960B - -Count = 224 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9646B9857FDA2E7241 - -Count = 225 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F967EDE4BFBE6960D8C - -Count = 226 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F965F23AC035D6499C7 - -Count = 227 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F96007B4B2D59E92EC5 - -Count = 228 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9696416FE28279E93E - -Count = 229 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F96B2491813D501EBDB - -Count = 230 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F96F85359AD298653C5 - -Count = 231 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F96C77AEE906CE621F5 - -Count = 232 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = -CT = C9034A2F7F9698A8EE4C09EF3E07AF - -Count = 233 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00 -CT = C9034A2F7F9698EF9305DBBA6EFD61 - -Count = 234 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001 -CT = C9034A2F7F96983D87C22A7B6DBA5C - -Count = 235 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102 -CT = C9034A2F7F969854DE7CD6838A27B3 - -Count = 236 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203 -CT = C9034A2F7F96983A22AF46F15548E7 - -Count = 237 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304 -CT = C9034A2F7F9698A0215878D888DD4D - -Count = 238 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405 -CT = C9034A2F7F9698AAEFB5BD89E1D90B - -Count = 239 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506 -CT = C9034A2F7F9698CCB7A8052516AE11 - -Count = 240 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304050607 -CT = C9034A2F7F9698579AAF25658CF4A5 - -Count = 241 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708 -CT = C9034A2F7F96989FDCDD7FF546E2CF - -Count = 242 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506070809 -CT = C9034A2F7F969874863538E788BCBF - -Count = 243 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A -CT = C9034A2F7F9698BBC41EDF168730F4 - -Count = 244 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B -CT = C9034A2F7F96984644C942167318F2 - -Count = 245 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F96981CCB5AB6E7BC8C0B - -Count = 246 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698E0B8E22BE49E395F - -Count = 247 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F969850FF5BB5F0C3F16D - -Count = 248 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F96983083F08873ECC89E - -Count = 249 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698E4A20D04CC3F0464 - -Count = 250 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698F7172C4AF643577C - -Count = 251 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698708B9EB0B88CE305 - -Count = 252 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698307FE408E470122A - -Count = 253 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F96980FDB5B1A7F693958 - -Count = 254 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698D3FA9B1E2CA942BB - -Count = 255 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F96984EDE68D88009743E - -Count = 256 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698028D5DC3F93D02B5 - -Count = 257 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F969894774ABBB886E6FF - -Count = 258 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698AC10843F843E9932 - -Count = 259 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F96988DED63C73FCC0D79 - -Count = 260 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698D2B584E93B41BA7B - -Count = 261 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698448FA026E0D17D80 - -Count = 262 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F96986087D7D7B7A97F65 - -Count = 263 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F96982A9D96694B2EC77B - -Count = 264 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F969815B421540E4EB54B - -Count = 265 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = -CT = C9034A2F7F9698DCFBF9B8E86994F2BE - -Count = 266 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00 -CT = C9034A2F7F9698DCBC84F13A3CC40870 - -Count = 267 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001 -CT = C9034A2F7F9698DC6E9036CBFDC74F4D - -Count = 268 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102 -CT = C9034A2F7F9698DC07C988370520D2A2 - -Count = 269 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203 -CT = C9034A2F7F9698DC69355BA777FFBDF6 - -Count = 270 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304 -CT = C9034A2F7F9698DCF336AC995E22285C - -Count = 271 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405 -CT = C9034A2F7F9698DCF9F8415C0F4B2C1A - -Count = 272 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506 -CT = C9034A2F7F9698DC9FA05CE4A3BC5B00 - -Count = 273 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304050607 -CT = C9034A2F7F9698DC048D5BC4E32601B4 - -Count = 274 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708 -CT = C9034A2F7F9698DCCCCB299E73EC17DE - -Count = 275 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506070809 -CT = C9034A2F7F9698DC2791C1D9612249AE - -Count = 276 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCE8D3EA3E902DC5E5 - -Count = 277 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DC15533DA390D9EDE3 - -Count = 278 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DC4FDCAE576116791A - -Count = 279 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB3AF16CA6234CC4E - -Count = 280 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DC03E8AF547669047C - -Count = 281 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DC63940469F5463D8F - -Count = 282 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB7B5F9E54A95F175 - -Count = 283 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCA400D8AB70E9A26D - -Count = 284 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DC239C6A513E261614 - -Count = 285 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DC636810E962DAE73B - -Count = 286 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DC5CCCAFFBF9C3CC49 - -Count = 287 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DC80ED6FFFAA03B7AA - -Count = 288 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DC1DC99C3906A3812F - -Count = 289 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DC519AA9227F97F7A4 - -Count = 290 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCC760BE5A3E2C13EE - -Count = 291 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCFF0770DE02946C23 - -Count = 292 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCDEFA9726B966F868 - -Count = 293 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DC81A27008BDEB4F6A - -Count = 294 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DC179854C7667B8891 - -Count = 295 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DC3390233631038A74 - -Count = 296 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DC798A6288CD84326A - -Count = 297 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DC46A3D5B588E4405A - -Count = 298 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = -CT = C9034A2F7F9698DCB420D003C709A0548E - -Count = 299 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00 -CT = C9034A2F7F9698DCB467AD4A155CF0AE40 - -Count = 300 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001 -CT = C9034A2F7F9698DCB4B5B98DE49DF3E97D - -Count = 301 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102 -CT = C9034A2F7F9698DCB4DCE0331865147492 - -Count = 302 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203 -CT = C9034A2F7F9698DCB4B21CE08817CB1BC6 - -Count = 303 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304 -CT = C9034A2F7F9698DCB4281F17B63E168E6C - -Count = 304 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405 -CT = C9034A2F7F9698DCB422D1FA736F7F8A2A - -Count = 305 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506 -CT = C9034A2F7F9698DCB44489E7CBC388FD30 - -Count = 306 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB4DFA4E0EB8312A784 - -Count = 307 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB417E292B113D8B1EE - -Count = 308 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB4FCB87AF60116EF9E - -Count = 309 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB433FA5111F01963D5 - -Count = 310 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB4CE7A868CF0ED4BD3 - -Count = 311 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB494F515780122DF2A - -Count = 312 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB46886ADE502006A7E - -Count = 313 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB4D8C1147B165DA24C - -Count = 314 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB4B8BDBF4695729BBF - -Count = 315 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB46C9C42CA2AA15745 - -Count = 316 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB47F29638410DD045D - -Count = 317 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB4F8B5D17E5E12B024 - -Count = 318 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB4B841ABC602EE410B - -Count = 319 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB487E514D499F76A79 - -Count = 320 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB45BC4D4D0CA37119A - -Count = 321 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB4C6E027166697271F - -Count = 322 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB48AB3120D1FA35194 - -Count = 323 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41C4905755E18B5DE - -Count = 324 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB4242ECBF162A0CA13 - -Count = 325 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB405D32C09D9525E58 - -Count = 326 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB45A8BCB27DDDFE95A - -Count = 327 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB4CCB1EFE8064F2EA1 - -Count = 328 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB4E8B9981951372C44 - -Count = 329 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB4A2A3D9A7ADB0945A - -Count = 330 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB49D8A6E9AE8D0E66A - -Count = 331 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = -CT = C9034A2F7F9698DCB41AB3B568223658767B - -Count = 332 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00 -CT = C9034A2F7F9698DCB41AF4C821F063088CB5 - -Count = 333 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001 -CT = C9034A2F7F9698DCB41A26DCE601A20BCB88 - -Count = 334 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102 -CT = C9034A2F7F9698DCB41A4F8558FD5AEC5667 - -Count = 335 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203 -CT = C9034A2F7F9698DCB41A21798B6D28333933 - -Count = 336 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ABB7A7C5301EEAC99 - -Count = 337 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405 -CT = C9034A2F7F9698DCB41AB1B491965087A8DF - -Count = 338 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41AD7EC8C2EFC70DFC5 - -Count = 339 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41A4CC18B0EBCEA8571 - -Count = 340 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41A8487F9542C20931B - -Count = 341 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41A6FDD11133EEECD6B - -Count = 342 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41AA09F3AF4CFE14120 - -Count = 343 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41A5D1FED69CF156926 - -Count = 344 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41A07907E9D3EDAFDDF - -Count = 345 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41AFBE3C6003DF8488B - -Count = 346 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41A4BA47F9E29A580B9 - -Count = 347 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41A2BD8D4A3AA8AB94A - -Count = 348 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41AFFF9292F155975B0 - -Count = 349 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41AEC4C08612F2526A8 - -Count = 350 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41A6BD0BA9B61EA92D1 - -Count = 351 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41A2B24C0233D1663FE - -Count = 352 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41A14807F31A60F488C - -Count = 353 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41AC8A1BF35F5CF336F - -Count = 354 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41A55854CF3596F05EA - -Count = 355 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41A19D679E8205B7361 - -Count = 356 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41A8F2C6E9061E0972B - -Count = 357 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41AB74BA0145D58E8E6 - -Count = 358 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41A96B647ECE6AA7CAD - -Count = 359 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41AC9EEA0C2E227CBAF - -Count = 360 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41A5FD4840D39B70C54 - -Count = 361 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41A7BDCF3FC6ECF0EB1 - -Count = 362 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41A31C6B2429248B6AF - -Count = 363 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41A0EEF057FD728C49F - -Count = 364 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = -CT = C9034A2F7F9698DCB41ACC7B4D6F307036DB5D - -Count = 365 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00 -CT = C9034A2F7F9698DCB41ACC3C3026E225662193 - -Count = 366 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001 -CT = C9034A2F7F9698DCB41ACCEE24E113E46566AE - -Count = 367 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102 -CT = C9034A2F7F9698DCB41ACC877D5FEF1C82FB41 - -Count = 368 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCE9818C7F6E5D9415 - -Count = 369 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACC73827B41478001BF - -Count = 370 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACC794C968416E905F9 - -Count = 371 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACC1F148B3CBA1E72E3 - -Count = 372 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACC84398C1CFA842857 - -Count = 373 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACC4C7FFE466A4E3E3D - -Count = 374 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCA72516017880604D - -Count = 375 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACC68673DE6898FEC06 - -Count = 376 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACC95E7EA7B897BC400 - -Count = 377 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCF68798F78B450F9 - -Count = 378 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACC331BC1127B96E5AD - -Count = 379 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACC835C788C6FCB2D9F - -Count = 380 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCE320D3B1ECE4146C - -Count = 381 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACC37012E3D5337D896 - -Count = 382 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACC24B40F73694B8B8E - -Count = 383 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCA328BD8927843FF7 - -Count = 384 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCE3DCC7317B78CED8 - -Count = 385 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCDC787823E061E5AA - -Count = 386 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACC0059B827B3A19E49 - -Count = 387 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACC9D7D4BE11F01A8CC - -Count = 388 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCD12E7EFA6635DE47 - -Count = 389 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACC47D46982278E3A0D - -Count = 390 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACC7FB3A7061B3645C0 - -Count = 391 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACC5E4E40FEA0C4D18B - -Count = 392 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACC0116A7D0A4496689 - -Count = 393 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACC972C831F7FD9A172 - -Count = 394 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCB324F4EE28A1A397 - -Count = 395 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCF93EB550D4261B89 - -Count = 396 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCC617026D914669B9 - -Count = 397 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = -CT = C9034A2F7F9698DCB41ACCCF2C8E9DBEE8D05718 - -Count = 398 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00 -CT = C9034A2F7F9698DCB41ACCCF6BF3D46CBD80ADD6 - -Count = 399 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFB9E7139D7C83EAEB - -Count = 400 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFD0BEAD6184647704 - -Count = 401 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBE427EF1F6BB1850 - -Count = 402 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCF244189CFDF668DFA - -Count = 403 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCF2E8F640A8E0F89BC - -Count = 404 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCF48D779B222F8FEA6 - -Count = 405 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFD3FA7E926262A412 - -Count = 406 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCF1BBC0CC8F2A8B278 - -Count = 407 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFF0E6E48FE066EC08 - -Count = 408 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCF3FA4CF6811696043 - -Count = 409 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFC22418F5119D4845 - -Count = 410 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCF98AB8B01E052DCBC - -Count = 411 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCF64D8339CE37069E8 - -Count = 412 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFD49F8A02F72DA1DA - -Count = 413 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFB4E3213F74029829 - -Count = 414 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCF60C2DCB3CBD154D3 - -Count = 415 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCF7377FDFDF1AD07CB - -Count = 416 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFF4EB4F07BF62B3B2 - -Count = 417 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFB41F35BFE39E429D - -Count = 418 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCF8BBB8AAD788769EF - -Count = 419 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCF579A4AA92B47120C - -Count = 420 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFCABEB96F87E72489 - -Count = 421 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCF86ED8C74FED35202 - -Count = 422 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCF10179B0CBF68B648 - -Count = 423 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCF2870558883D0C985 - -Count = 424 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCF098DB27038225DCE - -Count = 425 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCF56D5555E3CAFEACC - -Count = 426 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFC0EF7191E73F2D37 - -Count = 427 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFE4E70660B0472FD2 - -Count = 428 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFAEFD47DE4CC097CC - -Count = 429 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCF91D4F0E309A0E5FC - -Count = 430 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = -CT = C9034A2F7F9698DCB41ACCCFBF8457B65D560FE10C - -Count = 431 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBFC32AFF8F035F1BC2 - -Count = 432 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF113E387EC25C5CFF - -Count = 433 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF786786823ABBC110 - -Count = 434 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF169B55124864AE44 - -Count = 435 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF8C98A22C61B93BEE - -Count = 436 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF86564FE930D03FA8 - -Count = 437 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBFE00E52519C2748B2 - -Count = 438 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF7B235571DCBD1206 - -Count = 439 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBFB365272B4C77046C - -Count = 440 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF583FCF6C5EB95A1C - -Count = 441 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF977DE48BAFB6D657 - -Count = 442 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF6AFD3316AF42FE51 - -Count = 443 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF3072A0E25E8D6AA8 - -Count = 444 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBFCC01187F5DAFDFFC - -Count = 445 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF7C46A1E149F217CE - -Count = 446 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF1C3A0ADCCADD2E3D - -Count = 447 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBFC81BF750750EE2C7 - -Count = 448 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBFDBAED61E4F72B1DF - -Count = 449 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF5C3264E401BD05A6 - -Count = 450 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF1CC61E5C5D41F489 - -Count = 451 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF2362A14EC658DFFB - -Count = 452 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBFFF43614A9598A418 - -Count = 453 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF6267928C3938929D - -Count = 454 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF2E34A797400CE416 - -Count = 455 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBFB8CEB0EF01B7005C - -Count = 456 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF80A97E6B3D0F7F91 - -Count = 457 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBFA154999386FDEBDA - -Count = 458 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBFFE0C7EBD82705CD8 - -Count = 459 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF68365A7259E09B23 - -Count = 460 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF4C3E2D830E9899C6 - -Count = 461 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF06246C3DF21F21D8 - -Count = 462 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF390DDB00B77F53E8 - -Count = 463 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = -CT = C9034A2F7F9698DCB41ACCCFBF54A818514739035C87 - -Count = 464 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF54EF6518956C53A649 - -Count = 465 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF543D71DF64AD50E174 - -Count = 466 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF545428619855B77C9B - -Count = 467 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF543AD4B208276813CF - -Count = 468 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF54A0D745360EB58665 - -Count = 469 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF54AA19A8F35FDC8223 - -Count = 470 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF54CC41B54BF32BF539 - -Count = 471 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF54576CB26BB3B1AF8D - -Count = 472 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549F2AC031237BB9E7 - -Count = 473 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF547470287631B5E797 - -Count = 474 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF54BB320391C0BA6BDC - -Count = 475 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF5446B2D40CC04E43DA - -Count = 476 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF541C3D47F83181D723 - -Count = 477 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF54E04EFF6532A36277 - -Count = 478 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF54500946FB26FEAA45 - -Count = 479 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF543075EDC6A5D193B6 - -Count = 480 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF54E454104A1A025F4C - -Count = 481 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF54F7E13104207E0C54 - -Count = 482 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF54707D83FE6EB1B82D - -Count = 483 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF543089F946324D4902 - -Count = 484 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF540F2D4654A9546270 - -Count = 485 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF54D30C8650FA941993 - -Count = 486 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF544E28759656342F16 - -Count = 487 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF54027B408D2F00599D - -Count = 488 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF54948157F56EBBBDD7 - -Count = 489 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF54ACE699715203C21A - -Count = 490 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF548D1B7E89E9F15651 - -Count = 491 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF54D24399A7ED7CE153 - -Count = 492 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF544479BD6836EC26A8 - -Count = 493 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF546071CA996194244D - -Count = 494 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF542A6B8B279D139C53 - -Count = 495 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF5415423C1AD873EE63 - -Count = 496 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549B3902278F177E5A48 - -Count = 497 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549B7E7F6E5D422EA086 - -Count = 498 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BAC6BA9AC832DE7BB - -Count = 499 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BC53217507BCA7A54 - -Count = 500 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BABCEC4C009151500 - -Count = 501 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549B31CD33FE20C880AA - -Count = 502 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549B3B03DE3B71A184EC - -Count = 503 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549B5D5BC383DD56F3F6 - -Count = 504 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BC676C4A39DCCA942 - -Count = 505 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549B0E30B6F90D06BF28 - -Count = 506 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BE56A5EBE1FC8E158 - -Count = 507 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549B2A287559EEC76D13 - -Count = 508 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BD7A8A2C4EE334515 - -Count = 509 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549B8D2731301FFCD1EC - -Count = 510 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549B715489AD1CDE64B8 - -Count = 511 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BC11330330883AC8A - -Count = 512 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BA16F9B0E8BAC9579 - -Count = 513 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549B754E6682347F5983 - -Count = 514 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549B66FB47CC0E030A9B - -Count = 515 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BE167F53640CCBEE2 - -Count = 516 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BA1938F8E1C304FCD - -Count = 517 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549B9E37309C872964BF - -Count = 518 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549B4216F098D4E91F5C - -Count = 519 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BDF32035E784929D9 - -Count = 520 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549B93613645017D5F52 - -Count = 521 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549B059B213D40C6BB18 - -Count = 522 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549B3DFCEFB97C7EC4D5 - -Count = 523 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549B1C010841C78C509E - -Count = 524 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549B4359EF6FC301E79C - -Count = 525 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BD563CBA018912067 - -Count = 526 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF16BBC514FE92282 - -Count = 527 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BBB71FDEFB36E9A9C - -Count = 528 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549B84584AD2F60EE8AC - -Count = 529 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF7C152A8863B472BE1 - -Count = 530 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7862FE1546E17D12F - -Count = 531 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7543B26A5AF149612 - -Count = 532 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF73D62985957F30BFD - -Count = 533 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7539E4BC9252C64A9 - -Count = 534 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7C99DBCF70CF1F103 - -Count = 535 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7C35351325D98F545 - -Count = 536 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7A50B4C8AF16F825F - -Count = 537 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF73E264BAAB1F5D8EB - -Count = 538 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7F66039F0213FCE81 - -Count = 539 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF71D3AD1B733F190F1 - -Count = 540 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF7D278FA50C2FE1CBA - -Count = 541 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF72FF82DCDC20A34BC - -Count = 542 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF77577BE3933C5A045 - -Count = 543 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF7890406A430E71511 - -Count = 544 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF73943BF3A24BADD23 - -Count = 545 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF7593F1407A795E4D0 - -Count = 546 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF78D1EE98B1846282A - -Count = 547 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF79EABC8C5223A7B32 - -Count = 548 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF719377A3F6CF5CF4B - -Count = 549 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF759C3008730093E64 - -Count = 550 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF76667BF95AB101516 - -Count = 551 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7BA467F91F8D06EF5 - -Count = 552 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF727628C5754705870 - -Count = 553 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF76B31B94C2D442EFB - -Count = 554 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7FDCBAE346CFFCAB1 - -Count = 555 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7C5AC60B05047B57C - -Count = 556 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF7E4518748EBB52137 - -Count = 557 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF7BB096066EF389635 - -Count = 558 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF72D3344A934A851CE - -Count = 559 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF7093B335863D0532B - -Count = 560 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF7432172E69F57EB35 - -Count = 561 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF77C08C5DBDA379905 - -Count = 562 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747203F1717E3077918 - -Count = 563 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF74767425EC5B65783D6 - -Count = 564 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747B55699347754C4EB - -Count = 565 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747DC0F27C88FB35904 - -Count = 566 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747B2F3F458FD6C3650 - -Count = 567 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF74728F00366D4B1A3FA - -Count = 568 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747223EEEA385D8A7BC - -Count = 569 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7474466F31B292FD0A6 - -Count = 570 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747DF4BF43B69B58A12 - -Count = 571 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747170D8661F97F9C78 - -Count = 572 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747FC576E26EBB1C208 - -Count = 573 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747331545C11ABE4E43 - -Count = 574 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747CE95925C1A4A6645 - -Count = 575 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747941A01A8EB85F2BC - -Count = 576 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF7476869B935E8A747E8 - -Count = 577 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D82E00ABFCFA8FDA - -Count = 578 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747B852AB967FD5B629 - -Count = 579 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7476C73561AC0067AD3 - -Count = 580 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7477FC67754FA7A29CB - -Count = 581 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747F85AC5AEB4B59DB2 - -Count = 582 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747B8AEBF16E8496C9D - -Count = 583 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747870A0004735047EF - -Count = 584 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7475B2BC00020903C0C - -Count = 585 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747C60F33C68C300A89 - -Count = 586 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7478A5C06DDF5047C02 - -Count = 587 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF7471CA611A5B4BF9848 - -Count = 588 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF74724C1DF218807E785 - -Count = 589 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747053C38D933F573CE - -Count = 590 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF7475A64DFF73778C4CC - -Count = 591 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747CC5EFB38ECE80337 - -Count = 592 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747E8568CC9BB9001D2 - -Count = 593 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747A24CCD774717B9CC - -Count = 594 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF7479D657A4A0277CBFC - -Count = 595 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2B9A41F13A77A3797 - -Count = 596 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2FED956C1F22ACD59 - -Count = 597 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22CCD913033298A64 - -Count = 598 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D245942FCCCBCE178B - -Count = 599 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22B68FC5CB91178DF - -Count = 600 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2B16B0B6290CCED75 - -Count = 601 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2BBA5E6A7C1A5E933 - -Count = 602 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2DDFDFB1F6D529E29 - -Count = 603 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D0FC3F2DC8C49D - -Count = 604 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D28E968E65BD02D2F7 - -Count = 605 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D265CC6622AFCC8C87 - -Count = 606 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2AA8E4DC55EC300CC - -Count = 607 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2570E9A585E3728CA - -Count = 608 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D20D8109ACAFF8BC33 - -Count = 609 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2F1F2B131ACDA0967 - -Count = 610 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D241B508AFB887C155 - -Count = 611 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D221C9A3923BA8F8A6 - -Count = 612 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2F5E85E1E847B345C - -Count = 613 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2E65D7F50BE076744 - -Count = 614 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D261C1CDAAF0C8D33D - -Count = 615 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22135B712AC342212 - -Count = 616 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D21E910800372D0960 - -Count = 617 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2C2B0C80464ED7283 - -Count = 618 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D25F943BC2C84D4406 - -Count = 619 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D213C70ED9B179328D - -Count = 620 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2853D19A1F0C2D6C7 - -Count = 621 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2BD5AD725CC7AA90A - -Count = 622 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D29CA730DD77883D41 - -Count = 623 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2C3FFD7F373058A43 - -Count = 624 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D255C5F33CA8954DB8 - -Count = 625 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D271CD84CDFFED4F5D - -Count = 626 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D23BD7C573036AF743 - -Count = 627 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D204FE724E460A8573 - -Count = 628 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2463BBD4C88B61D2014 - -Count = 629 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2467CC0055AE34DDADA - -Count = 630 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246AED4C2AB224E9DE7 - -Count = 631 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C78D7C57DAA90008 - -Count = 632 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A971AFC7A8766F5C - -Count = 633 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246337258F981ABFAF6 - -Count = 634 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24639BCB53CD0C2FEB0 - -Count = 635 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2465FE4A8847C3589AA - -Count = 636 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C4C9AFA43CAFD31E - -Count = 637 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2460C8FDDFEAC65C574 - -Count = 638 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246E7D535B9BEAB9B04 - -Count = 639 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24628971E5E4FA4174F - -Count = 640 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D517C9C34F503F49 - -Count = 641 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2468F985A37BE9FABB0 - -Count = 642 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24673EBE2AABDBD1EE4 - -Count = 643 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C3AC5B34A9E0D6D6 - -Count = 644 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A3D0F0092ACFEF25 - -Count = 645 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24677F10D85951C23DF - -Count = 646 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24664442CCBAF6070C7 - -Count = 647 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246E3D89E31E1AFC4BE - -Count = 648 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A32CE489BD533591 - -Count = 649 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2469C885B9B264A1EE3 - -Count = 650 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24640A99B9F758A6500 - -Count = 651 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246DD8D6859D92A5385 - -Count = 652 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24691DE5D42A01E250E - -Count = 653 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24607244A3AE1A5C144 - -Count = 654 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2463F4384BEDD1DBE89 - -Count = 655 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2461EBE634666EF2AC2 - -Count = 656 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24641E6846862629DC0 - -Count = 657 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D7DCA0A7B9F25A3B - -Count = 658 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246F3D4D756EE8A58DE - -Count = 659 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246B9CE96E8120DE0C0 - -Count = 660 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24686E721D5576D92F0 - -Count = 661 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8350157EBDEE09FD2 - -Count = 662 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8727C1E398BB0651C - -Count = 663 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8A068D9C84AB32221 - -Count = 664 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8C9316734B254BFCE - -Count = 665 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8A7CDB4A4C08BD09A - -Count = 666 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A83DCE439AE9564530 - -Count = 667 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A83700AE5FB83F4176 - -Count = 668 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A85158B3E714C8366C - -Count = 669 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8CA75B4C754526CD8 - -Count = 670 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A80233C69DC4987AB2 - -Count = 671 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8E9692EDAD65624C2 - -Count = 672 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8262B053D2759A889 - -Count = 673 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8DBABD2A027AD808F - -Count = 674 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A881244154D6621476 - -Count = 675 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A87D57F9C9D540A122 - -Count = 676 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8CD104057C11D6910 - -Count = 677 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8AD6CEB6A423250E3 - -Count = 678 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8794D16E6FDE19C19 - -Count = 679 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86AF837A8C79DCF01 - -Count = 680 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8ED64855289527B78 - -Count = 681 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8AD90FFEAD5AE8A57 - -Count = 682 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8923440F84EB7A125 - -Count = 683 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A84E1580FC1D77DAC6 - -Count = 684 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8D331733AB1D7EC43 - -Count = 685 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A89F624621C8E39AC8 - -Count = 686 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A80998515989587E82 - -Count = 687 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A831FF9FDDB5E0014F - -Count = 688 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8100278250E129504 - -Count = 689 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A84F5A9F0B0A9F2206 - -Count = 690 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8D960BBC4D10FE5FD - -Count = 691 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8FD68CC358677E718 - -Count = 692 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8B7728D8B7AF05F06 - -Count = 693 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8885B3AB63F902D36 - -Count = 694 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86815CB8F49FB3DD784 - -Count = 695 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86852B6C69BAE6D2D4A - -Count = 696 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86880A2016A6F6E6A77 - -Count = 697 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868E9FBBF969789F798 - -Count = 698 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86887076C06E55698CC - -Count = 699 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8681D049B38CC8B0D66 - -Count = 700 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86817CA76FD9DE20920 - -Count = 701 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86871926B4531157E3A - -Count = 702 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868EABF6C65718F248E - -Count = 703 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86822F91E3FE14532E4 - -Count = 704 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868C9A3F678F38B6C94 - -Count = 705 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86806E1DD9F0284E0DF - -Count = 706 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FB610A020270C8D9 - -Count = 707 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868A1EE99F6F3BF5C20 - -Count = 708 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8685D9D216BF09DE974 - -Count = 709 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868EDDA98F5E4C02146 - -Count = 710 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8688DA633C867EF18B5 - -Count = 711 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8685987CE44D83CD44F - -Count = 712 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8684A32EF0AE2408757 - -Count = 713 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868CDAE5DF0AC8F332E - -Count = 714 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8688D5A2748F073C201 - -Count = 715 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868B2FE985A6B6AE973 - -Count = 716 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8686EDF585E38AA9290 - -Count = 717 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868F3FBAB98940AA415 - -Count = 718 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868BFA89E83ED3ED29E - -Count = 719 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868295289FBAC8536D4 - -Count = 720 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8681135477F903D4919 - -Count = 721 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86830C8A0872BCFDD52 - -Count = 722 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8686F9047A92F426A50 - -Count = 723 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868F9AA6366F4D2ADAB - -Count = 724 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868DDA21497A3AAAF4E - -Count = 725 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86897B855295F2D1750 - -Count = 726 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868A891E2141A4D6560 - -Count = 727 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5E43CB493E81906A - -Count = 728 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA193E829B6BD16AA4 - -Count = 729 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FACB2A456AAAD22D99 - -Count = 730 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA273FB965235B076 - -Count = 731 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FACC8F280620EADF22 - -Count = 732 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA568CDF3809374A88 - -Count = 733 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5C4232FD585E4ECE - -Count = 734 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA3A1A2F45F4A939D4 - -Count = 735 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA1372865B4336360 - -Count = 736 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA69715A3F24F9750A - -Count = 737 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA822BB27836372B7A - -Count = 738 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA4D69999FC738A731 - -Count = 739 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB0E94E02C7CC8F37 - -Count = 740 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAEA66DDF636031BCE - -Count = 741 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA1615656B3521AE9A - -Count = 742 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA652DCF5217C66A8 - -Count = 743 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAC62E77C8A2535F5B - -Count = 744 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA120F8A441D8093A1 - -Count = 745 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA01BAAB0A27FCC0B9 - -Count = 746 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA862619F0693374C0 - -Count = 747 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAC6D2634835CF85EF - -Count = 748 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAF976DC5AAED6AE9D - -Count = 749 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA25571C5EFD16D57E - -Count = 750 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB873EF9851B6E3FB - -Count = 751 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAF420DA8328829570 - -Count = 752 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA62DACDFB6939713A - -Count = 753 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5ABD037F55810EF7 - -Count = 754 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA7B40E487EE739ABC - -Count = 755 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA241803A9EAFE2DBE - -Count = 756 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB2222766316EEA45 - -Count = 757 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA962A50976616E8A0 - -Count = 758 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FADC3011299A9150BE - -Count = 759 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAE319A614DFF1228E - -Count = 760 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA3280659BC62EF69 - -Count = 761 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EE4554F8BE93215A7 - -Count = 762 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3641887A2831529A - -Count = 763 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5F183686D0D6CF75 - -Count = 764 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E31E4E516A209A021 - -Count = 765 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EABE712288BD4358B - -Count = 766 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA129FFEDDABD31CD - -Count = 767 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EC771E255764A46D7 - -Count = 768 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5C5CE57536D01C63 - -Count = 769 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E941A972FA61A0A09 - -Count = 770 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7F407F68B4D45479 - -Count = 771 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EB002548F45DBD832 - -Count = 772 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E4D828312452FF034 - -Count = 773 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E170D10E6B4E064CD - -Count = 774 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EEB7EA87BB7C2D199 - -Count = 775 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5B3911E5A39F19AB - -Count = 776 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3B45BAD820B02058 - -Count = 777 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EEF6447549F63ECA2 - -Count = 778 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EFCD1661AA51FBFBA - -Count = 779 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7B4DD4E0EBD00BC3 - -Count = 780 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3BB9AE58B72CFAEC - -Count = 781 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E041D114A2C35D19E - -Count = 782 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0ED83CD14E7FF5AA7D - -Count = 783 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E45182288D3559CF8 - -Count = 784 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E094B1793AA61EA73 - -Count = 785 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E9FB100EBEBDA0E39 - -Count = 786 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA7D6CE6FD76271F4 - -Count = 787 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E862B29976C90E5BF - -Count = 788 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0ED973CEB9681D52BD - -Count = 789 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E4F49EA76B38D9546 - -Count = 790 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E6B419D87E4F597A3 - -Count = 791 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E215BDC3918722FBD - -Count = 792 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E1E726B045D125D8D - -Count = 793 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760709018E833F1F5E - -Count = 794 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764074485CD66FE590 - -Count = 795 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7692608FAD176CA2AD - -Count = 796 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76FB393151EF8B3F42 - -Count = 797 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7695C5E2C19D545016 - -Count = 798 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760FC615FFB489C5BC - -Count = 799 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760508F83AE5E0C1FA - -Count = 800 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E766350E5824917B6E0 - -Count = 801 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76F87DE2A2098DEC54 - -Count = 802 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76303B90F89947FA3E - -Count = 803 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76DB6178BF8B89A44E - -Count = 804 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76142353587A862805 - -Count = 805 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76E9A384C57A720003 - -Count = 806 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76B32C17318BBD94FA - -Count = 807 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764F5FAFAC889F21AE - -Count = 808 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76FF1816329CC2E99C - -Count = 809 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E769F64BD0F1FEDD06F - -Count = 810 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764B454083A03E1C95 - -Count = 811 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7658F061CD9A424F8D - -Count = 812 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76DF6CD337D48DFBF4 - -Count = 813 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E769F98A98F88710ADB - -Count = 814 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76A03C169D136821A9 - -Count = 815 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E767C1DD69940A85A4A - -Count = 816 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76E139255FEC086CCF - -Count = 817 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76AD6A1044953C1A44 - -Count = 818 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E763B90073CD487FE0E - -Count = 819 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7603F7C9B8E83F81C3 - -Count = 820 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76220A2E4053CD1588 - -Count = 821 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E767D52C96E5740A28A - -Count = 822 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EB68EDA18CD06571 - -Count = 823 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76CF609A50DBA86794 - -Count = 824 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76857ADBEE272FDF8A - -Count = 825 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76BA536CD3624FADBA - -Count = 826 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD3F2C499CD01E93B - -Count = 827 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED948F8D4B985113F5 - -Count = 828 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED469B4ABA595254C8 - -Count = 829 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2FC2F446A1B5C927 - -Count = 830 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED413E27D6D36AA673 - -Count = 831 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDDB3DD0E8FAB733D9 - -Count = 832 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD1F33D2DABDE379F - -Count = 833 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDB7AB209507294085 - -Count = 834 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2C8627B547B31A31 - -Count = 835 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDE4C055EFD7790C5B - -Count = 836 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED0F9ABDA8C5B7522B - -Count = 837 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDC0D8964F34B8DE60 - -Count = 838 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED3D5841D2344CF666 - -Count = 839 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED67D7D226C583629F - -Count = 840 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED9BA46ABBC6A1D7CB - -Count = 841 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2BE3D325D2FC1FF9 - -Count = 842 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED4B9F781851D3260A - -Count = 843 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED9FBE8594EE00EAF0 - -Count = 844 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED8C0BA4DAD47CB9E8 - -Count = 845 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED0B9716209AB30D91 - -Count = 846 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED4B636C98C64FFCBE - -Count = 847 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED74C7D38A5D56D7CC - -Count = 848 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDA8E6138E0E96AC2F - -Count = 849 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED35C2E048A2369AAA - -Count = 850 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED7991D553DB02EC21 - -Count = 851 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDEF6BC22B9AB9086B - -Count = 852 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD70C0CAFA60177A6 - -Count = 853 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDF6F1EB571DF3E3ED - -Count = 854 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDA9A90C79197E54EF - -Count = 855 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED3F9328B6C2EE9314 - -Count = 856 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED1B9B5F47959691F1 - -Count = 857 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED51811EF9691129EF - -Count = 858 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED6EA8A9C42C715BDF - -Count = 859 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D60699C08C473E80 - -Count = 860 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27917BD012D917C44E - -Count = 861 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27436F17E318148373 - -Count = 862 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED272A36A91FE0F31E9C - -Count = 863 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2744CA7A8F922C71C8 - -Count = 864 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27DEC98DB1BBF1E462 - -Count = 865 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D4076074EA98E024 - -Count = 866 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27B25F7DCC466F973E - -Count = 867 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2729727AEC06F5CD8A - -Count = 868 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27E13408B6963FDBE0 - -Count = 869 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED270A6EE0F184F18590 - -Count = 870 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27C52CCB1675FE09DB - -Count = 871 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2738AC1C8B750A21DD - -Count = 872 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2762238F7F84C5B524 - -Count = 873 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED279E5037E287E70070 - -Count = 874 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED272E178E7C93BAC842 - -Count = 875 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED274E6B25411095F1B1 - -Count = 876 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED279A4AD8CDAF463D4B - -Count = 877 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2789FFF983953A6E53 - -Count = 878 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED270E634B79DBF5DA2A - -Count = 879 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED274E9731C187092B05 - -Count = 880 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2771338ED31C100077 - -Count = 881 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27AD124ED74FD07B94 - -Count = 882 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED273036BD11E3704D11 - -Count = 883 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED277C65880A9A443B9A - -Count = 884 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27EA9F9F72DBFFDFD0 - -Count = 885 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D2F851F6E747A01D - -Count = 886 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27F305B60E5CB53456 - -Count = 887 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27AC5D512058388354 - -Count = 888 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED273A6775EF83A844AF - -Count = 889 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED271E6F021ED4D0464A - -Count = 890 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27547543A02857FE54 - -Count = 891 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED276B5CF49D6D378C64 - -Count = 892 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA1D22EF9650CACD9F - -Count = 893 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA5A5FA644059A3751 - -Count = 894 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA884B61B5C499706C - -Count = 895 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE112DF493C7EED83 - -Count = 896 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA8FEE0CD94EA182D7 - -Count = 897 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA15EDFBE7677C177D - -Count = 898 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA1F2316223615133B - -Count = 899 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA797B0B9A9AE26421 - -Count = 900 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE2560CBADA783E95 - -Count = 901 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA2A107EE04AB228FF - -Count = 902 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAC14A96A7587C768F - -Count = 903 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0E08BD40A973FAC4 - -Count = 904 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAF3886ADDA987D2C2 - -Count = 905 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAA907F9295848463B - -Count = 906 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA557441B45B6AF36F - -Count = 907 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE533F82A4F373B5D - -Count = 908 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA854F5317CC1802AE - -Count = 909 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA516EAE9B73CBCE54 - -Count = 910 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA42DB8FD549B79D4C - -Count = 911 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAC5473D2F07782935 - -Count = 912 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA85B347975B84D81A - -Count = 913 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FABA17F885C09DF368 - -Count = 914 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA66363881935D888B - -Count = 915 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAFB12CB473FFDBE0E - -Count = 916 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAB741FE5C46C9C885 - -Count = 917 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA21BBE92407722CCF - -Count = 918 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA19DC27A03BCA5302 - -Count = 919 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA3821C0588038C749 - -Count = 920 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA6779277684B5704B - -Count = 921 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAF14303B95F25B7B0 - -Count = 922 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAD54B7448085DB555 - -Count = 923 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA9F5135F6F4DA0D4B - -Count = 924 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAA07882CBB1BA7F7B - -Count = 925 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF4E2AF1AD60EDADD - -Count = 926 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CB39FE6C8835E2013 - -Count = 927 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C618B2139425D672E - -Count = 928 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C08D29FC5BABAFAC1 - -Count = 929 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C662E4C55C8659595 - -Count = 930 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CFC2DBB6BE1B8003F - -Count = 931 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF6E356AEB0D10479 - -Count = 932 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C90BB4B161C267363 - -Count = 933 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C0B964C365CBC29D7 - -Count = 934 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CC3D03E6CCC763FBD - -Count = 935 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C288AD62BDEB861CD - -Count = 936 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CE7C8FDCC2FB7ED86 - -Count = 937 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C1A482A512F43C580 - -Count = 938 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C40C7B9A5DE8C5179 - -Count = 939 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CBCB40138DDAEE42D - -Count = 940 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C0CF3B8A6C9F32C1F - -Count = 941 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C6C8F139B4ADC15EC - -Count = 942 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CB8AEEE17F50FD916 - -Count = 943 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CAB1BCF59CF738A0E - -Count = 944 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2C877DA381BC3E77 - -Count = 945 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C6C73071BDD40CF58 - -Count = 946 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C53D7B8094659E42A - -Count = 947 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C8FF6780D15999FC9 - -Count = 948 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C12D28BCBB939A94C - -Count = 949 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C5E81BED0C00DDFC7 - -Count = 950 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CC87BA9A881B63B8D - -Count = 951 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF01C672CBD0E4440 - -Count = 952 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CD1E180D406FCD00B - -Count = 953 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C8EB967FA02716709 - -Count = 954 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C18834335D9E1A0F2 - -Count = 955 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C3C8B34C48E99A217 - -Count = 956 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C7691757A721E1A09 - -Count = 957 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C49B8C247377E6839 - -Count = 958 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E593E87D00022ED24 - -Count = 959 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E1E43CE02557217EA - -Count = 960 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2ECC5709F3947150D7 - -Count = 961 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA50EB70F6C96CD38 - -Count = 962 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2ECBF2649F1E49A26C - -Count = 963 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E51F193A1379437C6 - -Count = 964 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E5B3F7E6466FD3380 - -Count = 965 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3D6763DCCA0A449A - -Count = 966 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA64A64FC8A901E2E - -Count = 967 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E6E0C16A61A5A0844 - -Count = 968 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E8556FEE108945634 - -Count = 969 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E4A14D506F99BDA7F - -Count = 970 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EB794029BF96FF279 - -Count = 971 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EED1B916F08A06680 - -Count = 972 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E116829F20B82D3D4 - -Count = 973 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA12F906C1FDF1BE6 - -Count = 974 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EC1533B519CF02215 - -Count = 975 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E1572C6DD2323EEEF - -Count = 976 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E06C7E793195FBDF7 - -Count = 977 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E815B55695790098E - -Count = 978 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EC1AF2FD10B6CF8A1 - -Count = 979 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EFE0B90C39075D3D3 - -Count = 980 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E222A50C7C3B5A830 - -Count = 981 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EBF0EA3016F159EB5 - -Count = 982 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EF35D961A1621E83E - -Count = 983 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E65A78162579A0C74 - -Count = 984 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E5DC04FE66B2273B9 - -Count = 985 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E7C3DA81ED0D0E7F2 - -Count = 986 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E23654F30D45D50F0 - -Count = 987 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EB55F6BFF0FCD970B - -Count = 988 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E91571C0E58B595EE - -Count = 989 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EDB4D5DB0A4322DF0 - -Count = 990 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EE464EA8DE1525FC0 - -Count = 991 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335955C32AF45527B3 - -Count = 992 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E331E288AF8A105DD7D - -Count = 993 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33CC3C4D0960069A40 - -Count = 994 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A565F3F598E107AF - -Count = 995 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33CB992065EA3E68FB - -Count = 996 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33519AD75BC3E3FD51 - -Count = 997 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335B543A9E928AF917 - -Count = 998 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E333D0C27263E7D8E0D - -Count = 999 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A62120067EE7D4B9 - -Count = 1000 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336E67525CEE2DC2D3 - -Count = 1001 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33853DBA1BFCE39CA3 - -Count = 1002 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E334A7F91FC0DEC10E8 - -Count = 1003 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33B7FF46610D1838EE - -Count = 1004 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33ED70D595FCD7AC17 - -Count = 1005 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3311036D08FFF51943 - -Count = 1006 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A144D496EBA8D171 - -Count = 1007 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33C1387FAB6887E882 - -Count = 1008 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3315198227D7542478 - -Count = 1009 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3306ACA369ED287760 - -Count = 1010 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3381301193A3E7C319 - -Count = 1011 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33C1C46B2BFF1B3236 - -Count = 1012 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33FE60D43964021944 - -Count = 1013 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E332241143D37C262A7 - -Count = 1014 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33BF65E7FB9B625422 - -Count = 1015 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33F336D2E0E25622A9 - -Count = 1016 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365CCC598A3EDC6E3 - -Count = 1017 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335DAB0B1C9F55B92E - -Count = 1018 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E337C56ECE424A72D65 - -Count = 1019 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33230E0BCA202A9A67 - -Count = 1020 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33B5342F05FBBA5D9C - -Count = 1021 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33913C58F4ACC25F79 - -Count = 1022 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33DB26194A5045E767 - -Count = 1023 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33E40FAE7715259557 - -Count = 1024 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336519FC5173FEE9AC46 - -Count = 1025 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33655E8118A1ABB95688 - -Count = 1026 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658C95DF506ABA11B5 - -Count = 1027 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E5CC61AC925D8C5A - -Count = 1028 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658B30B23CE082E30E - -Count = 1029 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336511334502C95F76A4 - -Count = 1030 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33651BFDA8C7983672E2 - -Count = 1031 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33657DA5B57F34C105F8 - -Count = 1032 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E688B25F745B5F4C - -Count = 1033 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33652ECEC005E4914926 - -Count = 1034 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365C5942842F65F1756 - -Count = 1035 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33650AD603A507509B1D - -Count = 1036 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365F756D43807A4B31B - -Count = 1037 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365ADD947CCF66B27E2 - -Count = 1038 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336551AAFF51F54992B6 - -Count = 1039 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E1ED46CFE1145A84 - -Count = 1040 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658191EDF2623B6377 - -Count = 1041 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336555B0107EDDE8AF8D - -Count = 1042 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336546053130E794FC95 - -Count = 1043 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365C19983CAA95B48EC - -Count = 1044 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365816DF972F5A7B9C3 - -Count = 1045 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365BEC946606EBE92B1 - -Count = 1046 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336562E886643D7EE952 - -Count = 1047 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365FFCC75A291DEDFD7 - -Count = 1048 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365B39F40B9E8EAA95C - -Count = 1049 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365256557C1A9514D16 - -Count = 1050 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33651D02994595E932DB - -Count = 1051 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33653CFF7EBD2E1BA690 - -Count = 1052 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336563A799932A961192 - -Count = 1053 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365F59DBD5CF106D669 - -Count = 1054 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365D195CAADA67ED48C - -Count = 1055 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33659B8F8B135AF96C92 - -Count = 1056 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365A4A63C2E1F991EA2 - -Count = 1057 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBF84220B134F3973 - -Count = 1058 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF8F96BD9461FC3BD - -Count = 1059 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E2AEDAC28871C8480 - -Count = 1060 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E43B412D47FFB196F - -Count = 1061 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E2D48C1440D24763B - -Count = 1062 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EB74B367A24F9E391 - -Count = 1063 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBD85DBBF7590E7D7 - -Count = 1064 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EDBDDC607D96790CD - -Count = 1065 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304050607 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E40F0C12799FDCA79 - -Count = 1066 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E88B6B37D0937DC13 - -Count = 1067 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506070809 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E63EC5B3A1BF98263 - -Count = 1068 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EACAE70DDEAF60E28 - -Count = 1069 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E512EA740EA02262E - -Count = 1070 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E0BA134B41BCDB2D7 - -Count = 1071 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF7D28C2918EF0783 - -Count = 1072 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E479535B70CB2CFB1 - -Count = 1073 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E27E99E8A8F9DF642 - -Count = 1074 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF3C86306304E3AB8 - -Count = 1075 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EE07D42480A3269A0 - -Count = 1076 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E67E1F0B244FDDDD9 - -Count = 1077 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E27158A0A18012CF6 - -Count = 1078 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E18B1351883180784 - -Count = 1079 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EC490F51CD0D87C67 - -Count = 1080 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E59B406DA7C784AE2 - -Count = 1081 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E15E733C1054C3C69 - -Count = 1082 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E831D24B944F7D823 - -Count = 1083 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBB7AEA3D784FA7EE - -Count = 1084 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E9A870DC5C3BD33A5 - -Count = 1085 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EC5DFEAEBC73084A7 - -Count = 1086 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E53E5CE241CA0435C - -Count = 1087 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E77EDB9D54BD841B9 - -Count = 1088 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E3DF7F86BB75FF9A7 - -Count = 1089 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E02DE4F56F23F8B97 - +Count = 1 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = +CT = 99AD0D35BBB90AA7 + +Count = 2 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00 +CT = DED044E7EEE9F069 + +Count = 3 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001 +CT = 0CC483162FEAB754 + +Count = 4 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102 +CT = 659D3DEAD70D2ABB + +Count = 5 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203 +CT = 0B61EE7AA5D245EF + +Count = 6 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304 +CT = 916219448C0FD045 + +Count = 7 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405 +CT = 9BACF481DD66D403 + +Count = 8 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506 +CT = FDF4E9397191A319 + +Count = 9 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304050607 +CT = 66D9EE19310BF9AD + +Count = 10 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708 +CT = AE9F9C43A1C1EFC7 + +Count = 11 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506070809 +CT = 45C57404B30FB1B7 + +Count = 12 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A +CT = 8A875FE342003DFC + +Count = 13 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B +CT = 7707887E42F415FA + +Count = 14 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C +CT = 2D881B8AB33B8103 + +Count = 15 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D +CT = D1FBA317B0193457 + +Count = 16 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E +CT = 61BC1A89A444FC65 + +Count = 17 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F +CT = 01C0B1B4276BC596 + +Count = 18 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10 +CT = D5E14C3898B8096C + +Count = 19 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C6546D76A2C45A74 + +Count = 20 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 41C8DF8CEC0BEE0D + +Count = 21 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 013CA534B0F71F22 + +Count = 22 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 3E981A262BEE3450 + +Count = 23 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = E2B9DA22782E4FB3 + +Count = 24 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 7F9D29E4D48E7936 + +Count = 25 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 33CE1CFFADBA0FBD + +Count = 26 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = A5340B87EC01EBF7 + +Count = 27 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 9D53C503D0B9943A + +Count = 28 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = BCAE22FB6B4B0071 + +Count = 29 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = E3F6C5D56FC6B773 + +Count = 30 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75CCE11AB4567088 + +Count = 31 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 51C496EBE32E726D + +Count = 32 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 1BDED7551FA9CA73 + +Count = 33 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 24F760685AC9B843 + +Count = 34 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = +CT = C909DAD7810C416E41 + +Count = 35 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00 +CT = C94EA79E535911948F + +Count = 36 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001 +CT = C99CB359A29812D3B2 + +Count = 37 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102 +CT = C9F5EAE75E60F54E5D + +Count = 38 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203 +CT = C99B1634CE122A2109 + +Count = 39 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304 +CT = C90115C3F03BF7B4A3 + +Count = 40 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405 +CT = C90BDB2E356A9EB0E5 + +Count = 41 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506 +CT = C96D83338DC669C7FF + +Count = 42 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304050607 +CT = C9F6AE34AD86F39D4B + +Count = 43 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708 +CT = C93EE846F716398B21 + +Count = 44 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506070809 +CT = C9D5B2AEB004F7D551 + +Count = 45 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A +CT = C91AF08557F5F8591A + +Count = 46 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B +CT = C9E77052CAF50C711C + +Count = 47 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C +CT = C9BDFFC13E04C3E5E5 + +Count = 48 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D +CT = C9418C79A307E150B1 + +Count = 49 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E +CT = C9F1CBC03D13BC9883 + +Count = 50 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F +CT = C991B76B009093A170 + +Count = 51 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C94596968C2F406D8A + +Count = 52 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C95623B7C2153C3E92 + +Count = 53 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9D1BF05385BF38AEB + +Count = 54 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9914B7F80070F7BC4 + +Count = 55 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9AEEFC0929C1650B6 + +Count = 56 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C972CE0096CFD62B55 + +Count = 57 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9EFEAF35063761DD0 + +Count = 58 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9A3B9C64B1A426B5B + +Count = 59 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C93543D1335BF98F11 + +Count = 60 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C90D241FB76741F0DC + +Count = 61 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C92CD9F84FDCB36497 + +Count = 62 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C973811F61D83ED395 + +Count = 63 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9E5BB3BAE03AE146E + +Count = 64 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9C1B34C5F54D6168B + +Count = 65 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C98BA90DE1A851AE95 + +Count = 66 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9B480BADCED31DCA5 + +Count = 67 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = +CT = C90377F863D1D68B7D47 + +Count = 68 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00 +CT = C90330852A0383DB8789 + +Count = 69 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001 +CT = C903E291EDF242D8C0B4 + +Count = 70 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102 +CT = C9038BC8530EBA3F5D5B + +Count = 71 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203 +CT = C903E534809EC8E0320F + +Count = 72 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304 +CT = C9037F3777A0E13DA7A5 + +Count = 73 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405 +CT = C90375F99A65B054A3E3 + +Count = 74 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506 +CT = C90313A187DD1CA3D4F9 + +Count = 75 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304050607 +CT = C903888C80FD5C398E4D + +Count = 76 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708 +CT = C90340CAF2A7CCF39827 + +Count = 77 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506070809 +CT = C903AB901AE0DE3DC657 + +Count = 78 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A +CT = C90364D231072F324A1C + +Count = 79 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B +CT = C9039952E69A2FC6621A + +Count = 80 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C +CT = C903C3DD756EDE09F6E3 + +Count = 81 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D +CT = C9033FAECDF3DD2B43B7 + +Count = 82 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E +CT = C9038FE9746DC9768B85 + +Count = 83 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F +CT = C903EF95DF504A59B276 + +Count = 84 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9033BB422DCF58A7E8C + +Count = 85 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C90328010392CFF62D94 + +Count = 86 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C903AF9DB168813999ED + +Count = 87 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C903EF69CBD0DDC568C2 + +Count = 88 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C903D0CD74C246DC43B0 + +Count = 89 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9030CECB4C6151C3853 + +Count = 90 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C90391C84700B9BC0ED6 + +Count = 91 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C903DD9B721BC088785D + +Count = 92 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034B61656381339C17 + +Count = 93 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9037306ABE7BD8BE3DA + +Count = 94 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C90352FB4C1F06797791 + +Count = 95 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9030DA3AB3102F4C093 + +Count = 96 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9039B998FFED9640768 + +Count = 97 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C903BF91F80F8E1C058D + +Count = 98 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C903F58BB9B1729BBD93 + +Count = 99 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C903CAA20E8C37FBCFA3 + +Count = 100 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = +CT = C9034AEE97703E68E1AFAD + +Count = 101 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00 +CT = C9034AA9EA39EC3DB15563 + +Count = 102 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001 +CT = C9034A7BFEFE1DFCB2125E + +Count = 103 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102 +CT = C9034A12A740E104558FB1 + +Count = 104 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203 +CT = C9034A7C5B9371768AE0E5 + +Count = 105 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304 +CT = C9034AE658644F5F57754F + +Count = 106 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405 +CT = C9034AEC96898A0E3E7109 + +Count = 107 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506 +CT = C9034A8ACE9432A2C90613 + +Count = 108 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304050607 +CT = C9034A11E39312E2535CA7 + +Count = 109 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708 +CT = C9034AD9A5E14872994ACD + +Count = 110 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506070809 +CT = C9034A32FF090F605714BD + +Count = 111 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A +CT = C9034AFDBD22E8915898F6 + +Count = 112 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B +CT = C9034A003DF57591ACB0F0 + +Count = 113 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C +CT = C9034A5AB2668160632409 + +Count = 114 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D +CT = C9034AA6C1DE1C6341915D + +Count = 115 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A16866782771C596F + +Count = 116 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A76FACCBFF433609C + +Count = 117 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034AA2DB31334BE0AC66 + +Count = 118 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034AB16E107D719CFF7E + +Count = 119 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A36F2A2873F534B07 + +Count = 120 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A7606D83F63AFBA28 + +Count = 121 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A49A2672DF8B6915A + +Count = 122 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A9583A729AB76EAB9 + +Count = 123 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A08A754EF07D6DC3C + +Count = 124 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A44F461F47EE2AAB7 + +Count = 125 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034AD20E768C3F594EFD + +Count = 126 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034AEA69B80803E13130 + +Count = 127 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034ACB945FF0B813A57B + +Count = 128 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A94CCB8DEBC9E1279 + +Count = 129 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A02F69C11670ED582 + +Count = 130 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A26FEEBE03076D767 + +Count = 131 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A6CE4AA5ECCF16F79 + +Count = 132 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A53CD1D6389911D49 + +Count = 133 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = +CT = C9034A2FC5C3528515B7D64B + +Count = 134 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00 +CT = C9034A2F82BE1B5740E72C85 + +Count = 135 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001 +CT = C9034A2F50AADCA681E46BB8 + +Count = 136 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102 +CT = C9034A2F39F3625A7903F657 + +Count = 137 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203 +CT = C9034A2F570FB1CA0BDC9903 + +Count = 138 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304 +CT = C9034A2FCD0C46F422010CA9 + +Count = 139 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405 +CT = C9034A2FC7C2AB31736808EF + +Count = 140 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506 +CT = C9034A2FA19AB689DF9F7FF5 + +Count = 141 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304050607 +CT = C9034A2F3AB7B1A99F052541 + +Count = 142 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708 +CT = C9034A2FF2F1C3F30FCF332B + +Count = 143 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506070809 +CT = C9034A2F19AB2BB41D016D5B + +Count = 144 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A +CT = C9034A2FD6E90053EC0EE110 + +Count = 145 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B +CT = C9034A2F2B69D7CEECFAC916 + +Count = 146 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C +CT = C9034A2F71E6443A1D355DEF + +Count = 147 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F8D95FCA71E17E8BB + +Count = 148 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F3DD245390A4A2089 + +Count = 149 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F5DAEEE048965197A + +Count = 150 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F898F138836B6D580 + +Count = 151 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F9A3A32C60CCA8698 + +Count = 152 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F1DA6803C420532E1 + +Count = 153 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F5D52FA841EF9C3CE + +Count = 154 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F62F6459685E0E8BC + +Count = 155 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2FBED78592D620935F + +Count = 156 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F23F376547A80A5DA + +Count = 157 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F6FA0434F03B4D351 + +Count = 158 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2FF95A5437420F371B + +Count = 159 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2FC13D9AB37EB748D6 + +Count = 160 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2FE0C07D4BC545DC9D + +Count = 161 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2FBF989A65C1C86B9F + +Count = 162 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F29A2BEAA1A58AC64 + +Count = 163 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F0DAAC95B4D20AE81 + +Count = 164 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F47B088E5B1A7169F + +Count = 165 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F78993FD8F4C764AF + +Count = 166 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = +CT = C9034A2F7FC024F47371011925 + +Count = 167 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00 +CT = C9034A2F7F8759BDA12451E3EB + +Count = 168 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001 +CT = C9034A2F7F554D7A50E552A4D6 + +Count = 169 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102 +CT = C9034A2F7F3C14C4AC1DB53939 + +Count = 170 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203 +CT = C9034A2F7F52E8173C6F6A566D + +Count = 171 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304 +CT = C9034A2F7FC8EBE00246B7C3C7 + +Count = 172 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405 +CT = C9034A2F7FC2250DC717DEC781 + +Count = 173 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506 +CT = C9034A2F7FA47D107FBB29B09B + +Count = 174 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304050607 +CT = C9034A2F7F3F50175FFBB3EA2F + +Count = 175 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708 +CT = C9034A2F7FF71665056B79FC45 + +Count = 176 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506070809 +CT = C9034A2F7F1C4C8D4279B7A235 + +Count = 177 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A +CT = C9034A2F7FD30EA6A588B82E7E + +Count = 178 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B +CT = C9034A2F7F2E8E7138884C0678 + +Count = 179 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F7401E2CC79839281 + +Count = 180 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F88725A517AA127D5 + +Count = 181 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F3835E3CF6EFCEFE7 + +Count = 182 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F584948F2EDD3D614 + +Count = 183 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F8C68B57E52001AEE + +Count = 184 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9FDD9430687C49F6 + +Count = 185 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F184126CA26B3FD8F + +Count = 186 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F58B55C727A4F0CA0 + +Count = 187 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F6711E360E15627D2 + +Count = 188 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7FBB302364B2965C31 + +Count = 189 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F2614D0A21E366AB4 + +Count = 190 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F6A47E5B967021C3F + +Count = 191 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7FFCBDF2C126B9F875 + +Count = 192 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7FC4DA3C451A0187B8 + +Count = 193 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7FE527DBBDA1F313F3 + +Count = 194 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7FBA7F3C93A57EA4F1 + +Count = 195 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F2C45185C7EEE630A + +Count = 196 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F084D6FAD299661EF + +Count = 197 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F42572E13D511D9F1 + +Count = 198 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F7D7E992E9071ABC1 + +Count = 199 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = +CT = C9034A2F7F967A2083CD8D969311 + +Count = 200 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00 +CT = C9034A2F7F963D5DCA1FD8C669DF + +Count = 201 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001 +CT = C9034A2F7F96EF490DEE19C52EE2 + +Count = 202 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102 +CT = C9034A2F7F968610B312E122B30D + +Count = 203 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203 +CT = C9034A2F7F96E8EC608293FDDC59 + +Count = 204 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304 +CT = C9034A2F7F9672EF97BCBA2049F3 + +Count = 205 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405 +CT = C9034A2F7F9678217A79EB494DB5 + +Count = 206 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506 +CT = C9034A2F7F961E7967C147BE3AAF + +Count = 207 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304050607 +CT = C9034A2F7F96855460E10724601B + +Count = 208 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708 +CT = C9034A2F7F964D1212BB97EE7671 + +Count = 209 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506070809 +CT = C9034A2F7F96A648FAFC85202801 + +Count = 210 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A +CT = C9034A2F7F96690AD11B742FA44A + +Count = 211 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B +CT = C9034A2F7F96948A068674DB8C4C + +Count = 212 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F96CE059572851418B5 + +Count = 213 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9632762DEF8636ADE1 + +Count = 214 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9682319471926B65D3 + +Count = 215 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F96E24D3F4C11445C20 + +Count = 216 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F96366CC2C0AE9790DA + +Count = 217 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9625D9E38E94EBC3C2 + +Count = 218 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F96A2455174DA2477BB + +Count = 219 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F96E2B12BCC86D88694 + +Count = 220 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F96DD1594DE1DC1ADE6 + +Count = 221 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F96013454DA4E01D605 + +Count = 222 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F969C10A71CE2A1E080 + +Count = 223 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F96D04392079B95960B + +Count = 224 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9646B9857FDA2E7241 + +Count = 225 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F967EDE4BFBE6960D8C + +Count = 226 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F965F23AC035D6499C7 + +Count = 227 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F96007B4B2D59E92EC5 + +Count = 228 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9696416FE28279E93E + +Count = 229 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F96B2491813D501EBDB + +Count = 230 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F96F85359AD298653C5 + +Count = 231 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F96C77AEE906CE621F5 + +Count = 232 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = +CT = C9034A2F7F9698A8EE4C09EF3E07AF + +Count = 233 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00 +CT = C9034A2F7F9698EF9305DBBA6EFD61 + +Count = 234 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001 +CT = C9034A2F7F96983D87C22A7B6DBA5C + +Count = 235 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102 +CT = C9034A2F7F969854DE7CD6838A27B3 + +Count = 236 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203 +CT = C9034A2F7F96983A22AF46F15548E7 + +Count = 237 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304 +CT = C9034A2F7F9698A0215878D888DD4D + +Count = 238 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405 +CT = C9034A2F7F9698AAEFB5BD89E1D90B + +Count = 239 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506 +CT = C9034A2F7F9698CCB7A8052516AE11 + +Count = 240 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304050607 +CT = C9034A2F7F9698579AAF25658CF4A5 + +Count = 241 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708 +CT = C9034A2F7F96989FDCDD7FF546E2CF + +Count = 242 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506070809 +CT = C9034A2F7F969874863538E788BCBF + +Count = 243 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A +CT = C9034A2F7F9698BBC41EDF168730F4 + +Count = 244 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B +CT = C9034A2F7F96984644C942167318F2 + +Count = 245 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F96981CCB5AB6E7BC8C0B + +Count = 246 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698E0B8E22BE49E395F + +Count = 247 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F969850FF5BB5F0C3F16D + +Count = 248 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F96983083F08873ECC89E + +Count = 249 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698E4A20D04CC3F0464 + +Count = 250 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698F7172C4AF643577C + +Count = 251 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698708B9EB0B88CE305 + +Count = 252 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698307FE408E470122A + +Count = 253 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F96980FDB5B1A7F693958 + +Count = 254 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698D3FA9B1E2CA942BB + +Count = 255 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F96984EDE68D88009743E + +Count = 256 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698028D5DC3F93D02B5 + +Count = 257 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F969894774ABBB886E6FF + +Count = 258 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698AC10843F843E9932 + +Count = 259 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F96988DED63C73FCC0D79 + +Count = 260 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698D2B584E93B41BA7B + +Count = 261 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698448FA026E0D17D80 + +Count = 262 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F96986087D7D7B7A97F65 + +Count = 263 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F96982A9D96694B2EC77B + +Count = 264 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F969815B421540E4EB54B + +Count = 265 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = +CT = C9034A2F7F9698DCFBF9B8E86994F2BE + +Count = 266 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00 +CT = C9034A2F7F9698DCBC84F13A3CC40870 + +Count = 267 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001 +CT = C9034A2F7F9698DC6E9036CBFDC74F4D + +Count = 268 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102 +CT = C9034A2F7F9698DC07C988370520D2A2 + +Count = 269 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203 +CT = C9034A2F7F9698DC69355BA777FFBDF6 + +Count = 270 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304 +CT = C9034A2F7F9698DCF336AC995E22285C + +Count = 271 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405 +CT = C9034A2F7F9698DCF9F8415C0F4B2C1A + +Count = 272 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506 +CT = C9034A2F7F9698DC9FA05CE4A3BC5B00 + +Count = 273 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304050607 +CT = C9034A2F7F9698DC048D5BC4E32601B4 + +Count = 274 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708 +CT = C9034A2F7F9698DCCCCB299E73EC17DE + +Count = 275 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506070809 +CT = C9034A2F7F9698DC2791C1D9612249AE + +Count = 276 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCE8D3EA3E902DC5E5 + +Count = 277 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DC15533DA390D9EDE3 + +Count = 278 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DC4FDCAE576116791A + +Count = 279 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB3AF16CA6234CC4E + +Count = 280 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DC03E8AF547669047C + +Count = 281 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DC63940469F5463D8F + +Count = 282 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB7B5F9E54A95F175 + +Count = 283 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCA400D8AB70E9A26D + +Count = 284 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DC239C6A513E261614 + +Count = 285 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DC636810E962DAE73B + +Count = 286 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DC5CCCAFFBF9C3CC49 + +Count = 287 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DC80ED6FFFAA03B7AA + +Count = 288 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DC1DC99C3906A3812F + +Count = 289 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DC519AA9227F97F7A4 + +Count = 290 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCC760BE5A3E2C13EE + +Count = 291 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCFF0770DE02946C23 + +Count = 292 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCDEFA9726B966F868 + +Count = 293 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DC81A27008BDEB4F6A + +Count = 294 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DC179854C7667B8891 + +Count = 295 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DC3390233631038A74 + +Count = 296 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DC798A6288CD84326A + +Count = 297 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DC46A3D5B588E4405A + +Count = 298 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = +CT = C9034A2F7F9698DCB420D003C709A0548E + +Count = 299 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00 +CT = C9034A2F7F9698DCB467AD4A155CF0AE40 + +Count = 300 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001 +CT = C9034A2F7F9698DCB4B5B98DE49DF3E97D + +Count = 301 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102 +CT = C9034A2F7F9698DCB4DCE0331865147492 + +Count = 302 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203 +CT = C9034A2F7F9698DCB4B21CE08817CB1BC6 + +Count = 303 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304 +CT = C9034A2F7F9698DCB4281F17B63E168E6C + +Count = 304 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405 +CT = C9034A2F7F9698DCB422D1FA736F7F8A2A + +Count = 305 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506 +CT = C9034A2F7F9698DCB44489E7CBC388FD30 + +Count = 306 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB4DFA4E0EB8312A784 + +Count = 307 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB417E292B113D8B1EE + +Count = 308 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB4FCB87AF60116EF9E + +Count = 309 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB433FA5111F01963D5 + +Count = 310 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB4CE7A868CF0ED4BD3 + +Count = 311 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB494F515780122DF2A + +Count = 312 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB46886ADE502006A7E + +Count = 313 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB4D8C1147B165DA24C + +Count = 314 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB4B8BDBF4695729BBF + +Count = 315 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB46C9C42CA2AA15745 + +Count = 316 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB47F29638410DD045D + +Count = 317 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB4F8B5D17E5E12B024 + +Count = 318 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB4B841ABC602EE410B + +Count = 319 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB487E514D499F76A79 + +Count = 320 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB45BC4D4D0CA37119A + +Count = 321 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB4C6E027166697271F + +Count = 322 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB48AB3120D1FA35194 + +Count = 323 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41C4905755E18B5DE + +Count = 324 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB4242ECBF162A0CA13 + +Count = 325 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB405D32C09D9525E58 + +Count = 326 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB45A8BCB27DDDFE95A + +Count = 327 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB4CCB1EFE8064F2EA1 + +Count = 328 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB4E8B9981951372C44 + +Count = 329 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB4A2A3D9A7ADB0945A + +Count = 330 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB49D8A6E9AE8D0E66A + +Count = 331 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = +CT = C9034A2F7F9698DCB41AB3B568223658767B + +Count = 332 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00 +CT = C9034A2F7F9698DCB41AF4C821F063088CB5 + +Count = 333 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001 +CT = C9034A2F7F9698DCB41A26DCE601A20BCB88 + +Count = 334 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102 +CT = C9034A2F7F9698DCB41A4F8558FD5AEC5667 + +Count = 335 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203 +CT = C9034A2F7F9698DCB41A21798B6D28333933 + +Count = 336 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ABB7A7C5301EEAC99 + +Count = 337 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405 +CT = C9034A2F7F9698DCB41AB1B491965087A8DF + +Count = 338 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41AD7EC8C2EFC70DFC5 + +Count = 339 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41A4CC18B0EBCEA8571 + +Count = 340 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41A8487F9542C20931B + +Count = 341 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41A6FDD11133EEECD6B + +Count = 342 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41AA09F3AF4CFE14120 + +Count = 343 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41A5D1FED69CF156926 + +Count = 344 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41A07907E9D3EDAFDDF + +Count = 345 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41AFBE3C6003DF8488B + +Count = 346 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41A4BA47F9E29A580B9 + +Count = 347 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41A2BD8D4A3AA8AB94A + +Count = 348 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41AFFF9292F155975B0 + +Count = 349 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41AEC4C08612F2526A8 + +Count = 350 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41A6BD0BA9B61EA92D1 + +Count = 351 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41A2B24C0233D1663FE + +Count = 352 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41A14807F31A60F488C + +Count = 353 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41AC8A1BF35F5CF336F + +Count = 354 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41A55854CF3596F05EA + +Count = 355 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41A19D679E8205B7361 + +Count = 356 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41A8F2C6E9061E0972B + +Count = 357 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41AB74BA0145D58E8E6 + +Count = 358 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41A96B647ECE6AA7CAD + +Count = 359 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41AC9EEA0C2E227CBAF + +Count = 360 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41A5FD4840D39B70C54 + +Count = 361 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41A7BDCF3FC6ECF0EB1 + +Count = 362 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41A31C6B2429248B6AF + +Count = 363 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41A0EEF057FD728C49F + +Count = 364 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = +CT = C9034A2F7F9698DCB41ACC7B4D6F307036DB5D + +Count = 365 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00 +CT = C9034A2F7F9698DCB41ACC3C3026E225662193 + +Count = 366 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001 +CT = C9034A2F7F9698DCB41ACCEE24E113E46566AE + +Count = 367 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102 +CT = C9034A2F7F9698DCB41ACC877D5FEF1C82FB41 + +Count = 368 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCE9818C7F6E5D9415 + +Count = 369 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACC73827B41478001BF + +Count = 370 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACC794C968416E905F9 + +Count = 371 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACC1F148B3CBA1E72E3 + +Count = 372 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACC84398C1CFA842857 + +Count = 373 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACC4C7FFE466A4E3E3D + +Count = 374 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCA72516017880604D + +Count = 375 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACC68673DE6898FEC06 + +Count = 376 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACC95E7EA7B897BC400 + +Count = 377 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCF68798F78B450F9 + +Count = 378 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACC331BC1127B96E5AD + +Count = 379 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACC835C788C6FCB2D9F + +Count = 380 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCE320D3B1ECE4146C + +Count = 381 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACC37012E3D5337D896 + +Count = 382 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACC24B40F73694B8B8E + +Count = 383 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCA328BD8927843FF7 + +Count = 384 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCE3DCC7317B78CED8 + +Count = 385 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCDC787823E061E5AA + +Count = 386 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACC0059B827B3A19E49 + +Count = 387 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACC9D7D4BE11F01A8CC + +Count = 388 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCD12E7EFA6635DE47 + +Count = 389 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACC47D46982278E3A0D + +Count = 390 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACC7FB3A7061B3645C0 + +Count = 391 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACC5E4E40FEA0C4D18B + +Count = 392 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACC0116A7D0A4496689 + +Count = 393 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACC972C831F7FD9A172 + +Count = 394 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCB324F4EE28A1A397 + +Count = 395 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCF93EB550D4261B89 + +Count = 396 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCC617026D914669B9 + +Count = 397 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = +CT = C9034A2F7F9698DCB41ACCCF2C8E9DBEE8D05718 + +Count = 398 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00 +CT = C9034A2F7F9698DCB41ACCCF6BF3D46CBD80ADD6 + +Count = 399 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFB9E7139D7C83EAEB + +Count = 400 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFD0BEAD6184647704 + +Count = 401 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBE427EF1F6BB1850 + +Count = 402 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCF244189CFDF668DFA + +Count = 403 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCF2E8F640A8E0F89BC + +Count = 404 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCF48D779B222F8FEA6 + +Count = 405 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFD3FA7E926262A412 + +Count = 406 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCF1BBC0CC8F2A8B278 + +Count = 407 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFF0E6E48FE066EC08 + +Count = 408 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCF3FA4CF6811696043 + +Count = 409 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFC22418F5119D4845 + +Count = 410 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCF98AB8B01E052DCBC + +Count = 411 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCF64D8339CE37069E8 + +Count = 412 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFD49F8A02F72DA1DA + +Count = 413 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFB4E3213F74029829 + +Count = 414 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCF60C2DCB3CBD154D3 + +Count = 415 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCF7377FDFDF1AD07CB + +Count = 416 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFF4EB4F07BF62B3B2 + +Count = 417 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFB41F35BFE39E429D + +Count = 418 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCF8BBB8AAD788769EF + +Count = 419 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCF579A4AA92B47120C + +Count = 420 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFCABEB96F87E72489 + +Count = 421 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCF86ED8C74FED35202 + +Count = 422 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCF10179B0CBF68B648 + +Count = 423 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCF2870558883D0C985 + +Count = 424 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCF098DB27038225DCE + +Count = 425 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCF56D5555E3CAFEACC + +Count = 426 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFC0EF7191E73F2D37 + +Count = 427 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFE4E70660B0472FD2 + +Count = 428 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFAEFD47DE4CC097CC + +Count = 429 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCF91D4F0E309A0E5FC + +Count = 430 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = +CT = C9034A2F7F9698DCB41ACCCFBF8457B65D560FE10C + +Count = 431 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBFC32AFF8F035F1BC2 + +Count = 432 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF113E387EC25C5CFF + +Count = 433 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF786786823ABBC110 + +Count = 434 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF169B55124864AE44 + +Count = 435 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF8C98A22C61B93BEE + +Count = 436 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF86564FE930D03FA8 + +Count = 437 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBFE00E52519C2748B2 + +Count = 438 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF7B235571DCBD1206 + +Count = 439 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBFB365272B4C77046C + +Count = 440 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF583FCF6C5EB95A1C + +Count = 441 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF977DE48BAFB6D657 + +Count = 442 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF6AFD3316AF42FE51 + +Count = 443 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF3072A0E25E8D6AA8 + +Count = 444 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBFCC01187F5DAFDFFC + +Count = 445 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF7C46A1E149F217CE + +Count = 446 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF1C3A0ADCCADD2E3D + +Count = 447 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBFC81BF750750EE2C7 + +Count = 448 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBFDBAED61E4F72B1DF + +Count = 449 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF5C3264E401BD05A6 + +Count = 450 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF1CC61E5C5D41F489 + +Count = 451 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF2362A14EC658DFFB + +Count = 452 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBFFF43614A9598A418 + +Count = 453 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF6267928C3938929D + +Count = 454 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF2E34A797400CE416 + +Count = 455 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBFB8CEB0EF01B7005C + +Count = 456 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF80A97E6B3D0F7F91 + +Count = 457 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBFA154999386FDEBDA + +Count = 458 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBFFE0C7EBD82705CD8 + +Count = 459 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF68365A7259E09B23 + +Count = 460 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF4C3E2D830E9899C6 + +Count = 461 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF06246C3DF21F21D8 + +Count = 462 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF390DDB00B77F53E8 + +Count = 463 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = +CT = C9034A2F7F9698DCB41ACCCFBF54A818514739035C87 + +Count = 464 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF54EF6518956C53A649 + +Count = 465 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF543D71DF64AD50E174 + +Count = 466 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF545428619855B77C9B + +Count = 467 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF543AD4B208276813CF + +Count = 468 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF54A0D745360EB58665 + +Count = 469 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF54AA19A8F35FDC8223 + +Count = 470 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF54CC41B54BF32BF539 + +Count = 471 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF54576CB26BB3B1AF8D + +Count = 472 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549F2AC031237BB9E7 + +Count = 473 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF547470287631B5E797 + +Count = 474 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF54BB320391C0BA6BDC + +Count = 475 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF5446B2D40CC04E43DA + +Count = 476 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF541C3D47F83181D723 + +Count = 477 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF54E04EFF6532A36277 + +Count = 478 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF54500946FB26FEAA45 + +Count = 479 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF543075EDC6A5D193B6 + +Count = 480 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF54E454104A1A025F4C + +Count = 481 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF54F7E13104207E0C54 + +Count = 482 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF54707D83FE6EB1B82D + +Count = 483 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF543089F946324D4902 + +Count = 484 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF540F2D4654A9546270 + +Count = 485 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF54D30C8650FA941993 + +Count = 486 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF544E28759656342F16 + +Count = 487 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF54027B408D2F00599D + +Count = 488 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF54948157F56EBBBDD7 + +Count = 489 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF54ACE699715203C21A + +Count = 490 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF548D1B7E89E9F15651 + +Count = 491 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF54D24399A7ED7CE153 + +Count = 492 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF544479BD6836EC26A8 + +Count = 493 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF546071CA996194244D + +Count = 494 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF542A6B8B279D139C53 + +Count = 495 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF5415423C1AD873EE63 + +Count = 496 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549B3902278F177E5A48 + +Count = 497 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549B7E7F6E5D422EA086 + +Count = 498 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BAC6BA9AC832DE7BB + +Count = 499 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BC53217507BCA7A54 + +Count = 500 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BABCEC4C009151500 + +Count = 501 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549B31CD33FE20C880AA + +Count = 502 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549B3B03DE3B71A184EC + +Count = 503 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549B5D5BC383DD56F3F6 + +Count = 504 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BC676C4A39DCCA942 + +Count = 505 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549B0E30B6F90D06BF28 + +Count = 506 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BE56A5EBE1FC8E158 + +Count = 507 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549B2A287559EEC76D13 + +Count = 508 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BD7A8A2C4EE334515 + +Count = 509 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549B8D2731301FFCD1EC + +Count = 510 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549B715489AD1CDE64B8 + +Count = 511 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BC11330330883AC8A + +Count = 512 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BA16F9B0E8BAC9579 + +Count = 513 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549B754E6682347F5983 + +Count = 514 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549B66FB47CC0E030A9B + +Count = 515 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BE167F53640CCBEE2 + +Count = 516 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BA1938F8E1C304FCD + +Count = 517 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549B9E37309C872964BF + +Count = 518 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549B4216F098D4E91F5C + +Count = 519 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BDF32035E784929D9 + +Count = 520 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549B93613645017D5F52 + +Count = 521 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549B059B213D40C6BB18 + +Count = 522 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549B3DFCEFB97C7EC4D5 + +Count = 523 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549B1C010841C78C509E + +Count = 524 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549B4359EF6FC301E79C + +Count = 525 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BD563CBA018912067 + +Count = 526 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF16BBC514FE92282 + +Count = 527 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BBB71FDEFB36E9A9C + +Count = 528 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549B84584AD2F60EE8AC + +Count = 529 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF7C152A8863B472BE1 + +Count = 530 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7862FE1546E17D12F + +Count = 531 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7543B26A5AF149612 + +Count = 532 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF73D62985957F30BFD + +Count = 533 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7539E4BC9252C64A9 + +Count = 534 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7C99DBCF70CF1F103 + +Count = 535 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7C35351325D98F545 + +Count = 536 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7A50B4C8AF16F825F + +Count = 537 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF73E264BAAB1F5D8EB + +Count = 538 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7F66039F0213FCE81 + +Count = 539 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF71D3AD1B733F190F1 + +Count = 540 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF7D278FA50C2FE1CBA + +Count = 541 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF72FF82DCDC20A34BC + +Count = 542 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF77577BE3933C5A045 + +Count = 543 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF7890406A430E71511 + +Count = 544 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF73943BF3A24BADD23 + +Count = 545 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF7593F1407A795E4D0 + +Count = 546 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF78D1EE98B1846282A + +Count = 547 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF79EABC8C5223A7B32 + +Count = 548 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF719377A3F6CF5CF4B + +Count = 549 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF759C3008730093E64 + +Count = 550 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF76667BF95AB101516 + +Count = 551 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7BA467F91F8D06EF5 + +Count = 552 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF727628C5754705870 + +Count = 553 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF76B31B94C2D442EFB + +Count = 554 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7FDCBAE346CFFCAB1 + +Count = 555 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7C5AC60B05047B57C + +Count = 556 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF7E4518748EBB52137 + +Count = 557 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF7BB096066EF389635 + +Count = 558 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF72D3344A934A851CE + +Count = 559 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF7093B335863D0532B + +Count = 560 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF7432172E69F57EB35 + +Count = 561 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF77C08C5DBDA379905 + +Count = 562 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747203F1717E3077918 + +Count = 563 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF74767425EC5B65783D6 + +Count = 564 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747B55699347754C4EB + +Count = 565 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747DC0F27C88FB35904 + +Count = 566 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747B2F3F458FD6C3650 + +Count = 567 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF74728F00366D4B1A3FA + +Count = 568 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747223EEEA385D8A7BC + +Count = 569 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7474466F31B292FD0A6 + +Count = 570 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747DF4BF43B69B58A12 + +Count = 571 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747170D8661F97F9C78 + +Count = 572 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747FC576E26EBB1C208 + +Count = 573 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747331545C11ABE4E43 + +Count = 574 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747CE95925C1A4A6645 + +Count = 575 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747941A01A8EB85F2BC + +Count = 576 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF7476869B935E8A747E8 + +Count = 577 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D82E00ABFCFA8FDA + +Count = 578 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747B852AB967FD5B629 + +Count = 579 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7476C73561AC0067AD3 + +Count = 580 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7477FC67754FA7A29CB + +Count = 581 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747F85AC5AEB4B59DB2 + +Count = 582 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747B8AEBF16E8496C9D + +Count = 583 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747870A0004735047EF + +Count = 584 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7475B2BC00020903C0C + +Count = 585 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747C60F33C68C300A89 + +Count = 586 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7478A5C06DDF5047C02 + +Count = 587 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF7471CA611A5B4BF9848 + +Count = 588 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF74724C1DF218807E785 + +Count = 589 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747053C38D933F573CE + +Count = 590 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF7475A64DFF73778C4CC + +Count = 591 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747CC5EFB38ECE80337 + +Count = 592 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747E8568CC9BB9001D2 + +Count = 593 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747A24CCD774717B9CC + +Count = 594 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF7479D657A4A0277CBFC + +Count = 595 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2B9A41F13A77A3797 + +Count = 596 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2FED956C1F22ACD59 + +Count = 597 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22CCD913033298A64 + +Count = 598 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D245942FCCCBCE178B + +Count = 599 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22B68FC5CB91178DF + +Count = 600 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2B16B0B6290CCED75 + +Count = 601 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2BBA5E6A7C1A5E933 + +Count = 602 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2DDFDFB1F6D529E29 + +Count = 603 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D0FC3F2DC8C49D + +Count = 604 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D28E968E65BD02D2F7 + +Count = 605 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D265CC6622AFCC8C87 + +Count = 606 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2AA8E4DC55EC300CC + +Count = 607 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2570E9A585E3728CA + +Count = 608 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D20D8109ACAFF8BC33 + +Count = 609 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2F1F2B131ACDA0967 + +Count = 610 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D241B508AFB887C155 + +Count = 611 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D221C9A3923BA8F8A6 + +Count = 612 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2F5E85E1E847B345C + +Count = 613 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2E65D7F50BE076744 + +Count = 614 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D261C1CDAAF0C8D33D + +Count = 615 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D22135B712AC342212 + +Count = 616 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D21E910800372D0960 + +Count = 617 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2C2B0C80464ED7283 + +Count = 618 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D25F943BC2C84D4406 + +Count = 619 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D213C70ED9B179328D + +Count = 620 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2853D19A1F0C2D6C7 + +Count = 621 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2BD5AD725CC7AA90A + +Count = 622 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D29CA730DD77883D41 + +Count = 623 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2C3FFD7F373058A43 + +Count = 624 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D255C5F33CA8954DB8 + +Count = 625 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D271CD84CDFFED4F5D + +Count = 626 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D23BD7C573036AF743 + +Count = 627 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D204FE724E460A8573 + +Count = 628 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2463BBD4C88B61D2014 + +Count = 629 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2467CC0055AE34DDADA + +Count = 630 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246AED4C2AB224E9DE7 + +Count = 631 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C78D7C57DAA90008 + +Count = 632 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A971AFC7A8766F5C + +Count = 633 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246337258F981ABFAF6 + +Count = 634 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24639BCB53CD0C2FEB0 + +Count = 635 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2465FE4A8847C3589AA + +Count = 636 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C4C9AFA43CAFD31E + +Count = 637 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2460C8FDDFEAC65C574 + +Count = 638 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246E7D535B9BEAB9B04 + +Count = 639 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24628971E5E4FA4174F + +Count = 640 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D517C9C34F503F49 + +Count = 641 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2468F985A37BE9FABB0 + +Count = 642 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24673EBE2AABDBD1EE4 + +Count = 643 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246C3AC5B34A9E0D6D6 + +Count = 644 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A3D0F0092ACFEF25 + +Count = 645 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24677F10D85951C23DF + +Count = 646 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24664442CCBAF6070C7 + +Count = 647 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246E3D89E31E1AFC4BE + +Count = 648 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A32CE489BD533591 + +Count = 649 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2469C885B9B264A1EE3 + +Count = 650 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24640A99B9F758A6500 + +Count = 651 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246DD8D6859D92A5385 + +Count = 652 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24691DE5D42A01E250E + +Count = 653 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24607244A3AE1A5C144 + +Count = 654 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2463F4384BEDD1DBE89 + +Count = 655 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D2461EBE634666EF2AC2 + +Count = 656 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24641E6846862629DC0 + +Count = 657 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246D7DCA0A7B9F25A3B + +Count = 658 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246F3D4D756EE8A58DE + +Count = 659 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246B9CE96E8120DE0C0 + +Count = 660 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D24686E721D5576D92F0 + +Count = 661 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8350157EBDEE09FD2 + +Count = 662 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8727C1E398BB0651C + +Count = 663 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8A068D9C84AB32221 + +Count = 664 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8C9316734B254BFCE + +Count = 665 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8A7CDB4A4C08BD09A + +Count = 666 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A83DCE439AE9564530 + +Count = 667 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A83700AE5FB83F4176 + +Count = 668 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A85158B3E714C8366C + +Count = 669 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8CA75B4C754526CD8 + +Count = 670 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A80233C69DC4987AB2 + +Count = 671 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8E9692EDAD65624C2 + +Count = 672 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8262B053D2759A889 + +Count = 673 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8DBABD2A027AD808F + +Count = 674 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A881244154D6621476 + +Count = 675 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A87D57F9C9D540A122 + +Count = 676 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8CD104057C11D6910 + +Count = 677 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8AD6CEB6A423250E3 + +Count = 678 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8794D16E6FDE19C19 + +Count = 679 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86AF837A8C79DCF01 + +Count = 680 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8ED64855289527B78 + +Count = 681 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8AD90FFEAD5AE8A57 + +Count = 682 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8923440F84EB7A125 + +Count = 683 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A84E1580FC1D77DAC6 + +Count = 684 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8D331733AB1D7EC43 + +Count = 685 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A89F624621C8E39AC8 + +Count = 686 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A80998515989587E82 + +Count = 687 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A831FF9FDDB5E0014F + +Count = 688 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8100278250E129504 + +Count = 689 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A84F5A9F0B0A9F2206 + +Count = 690 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8D960BBC4D10FE5FD + +Count = 691 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8FD68CC358677E718 + +Count = 692 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8B7728D8B7AF05F06 + +Count = 693 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8885B3AB63F902D36 + +Count = 694 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86815CB8F49FB3DD784 + +Count = 695 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86852B6C69BAE6D2D4A + +Count = 696 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86880A2016A6F6E6A77 + +Count = 697 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868E9FBBF969789F798 + +Count = 698 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86887076C06E55698CC + +Count = 699 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8681D049B38CC8B0D66 + +Count = 700 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86817CA76FD9DE20920 + +Count = 701 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86871926B4531157E3A + +Count = 702 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868EABF6C65718F248E + +Count = 703 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86822F91E3FE14532E4 + +Count = 704 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868C9A3F678F38B6C94 + +Count = 705 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86806E1DD9F0284E0DF + +Count = 706 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FB610A020270C8D9 + +Count = 707 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868A1EE99F6F3BF5C20 + +Count = 708 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8685D9D216BF09DE974 + +Count = 709 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868EDDA98F5E4C02146 + +Count = 710 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8688DA633C867EF18B5 + +Count = 711 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8685987CE44D83CD44F + +Count = 712 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8684A32EF0AE2408757 + +Count = 713 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868CDAE5DF0AC8F332E + +Count = 714 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8688D5A2748F073C201 + +Count = 715 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868B2FE985A6B6AE973 + +Count = 716 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8686EDF585E38AA9290 + +Count = 717 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868F3FBAB98940AA415 + +Count = 718 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868BFA89E83ED3ED29E + +Count = 719 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868295289FBAC8536D4 + +Count = 720 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8681135477F903D4919 + +Count = 721 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86830C8A0872BCFDD52 + +Count = 722 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A8686F9047A92F426A50 + +Count = 723 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868F9AA6366F4D2ADAB + +Count = 724 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868DDA21497A3AAAF4E + +Count = 725 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A86897B855295F2D1750 + +Count = 726 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868A891E2141A4D6560 + +Count = 727 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5E43CB493E81906A + +Count = 728 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA193E829B6BD16AA4 + +Count = 729 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FACB2A456AAAD22D99 + +Count = 730 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA273FB965235B076 + +Count = 731 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FACC8F280620EADF22 + +Count = 732 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA568CDF3809374A88 + +Count = 733 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5C4232FD585E4ECE + +Count = 734 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA3A1A2F45F4A939D4 + +Count = 735 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA1372865B4336360 + +Count = 736 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA69715A3F24F9750A + +Count = 737 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA822BB27836372B7A + +Count = 738 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA4D69999FC738A731 + +Count = 739 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB0E94E02C7CC8F37 + +Count = 740 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAEA66DDF636031BCE + +Count = 741 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA1615656B3521AE9A + +Count = 742 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAA652DCF5217C66A8 + +Count = 743 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAC62E77C8A2535F5B + +Count = 744 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA120F8A441D8093A1 + +Count = 745 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA01BAAB0A27FCC0B9 + +Count = 746 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA862619F0693374C0 + +Count = 747 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAC6D2634835CF85EF + +Count = 748 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAF976DC5AAED6AE9D + +Count = 749 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA25571C5EFD16D57E + +Count = 750 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB873EF9851B6E3FB + +Count = 751 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAF420DA8328829570 + +Count = 752 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA62DACDFB6939713A + +Count = 753 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA5ABD037F55810EF7 + +Count = 754 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA7B40E487EE739ABC + +Count = 755 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA241803A9EAFE2DBE + +Count = 756 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAB2222766316EEA45 + +Count = 757 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA962A50976616E8A0 + +Count = 758 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FADC3011299A9150BE + +Count = 759 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FAE319A614DFF1228E + +Count = 760 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA3280659BC62EF69 + +Count = 761 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EE4554F8BE93215A7 + +Count = 762 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3641887A2831529A + +Count = 763 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5F183686D0D6CF75 + +Count = 764 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E31E4E516A209A021 + +Count = 765 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EABE712288BD4358B + +Count = 766 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA129FFEDDABD31CD + +Count = 767 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EC771E255764A46D7 + +Count = 768 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5C5CE57536D01C63 + +Count = 769 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E941A972FA61A0A09 + +Count = 770 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7F407F68B4D45479 + +Count = 771 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EB002548F45DBD832 + +Count = 772 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E4D828312452FF034 + +Count = 773 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E170D10E6B4E064CD + +Count = 774 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EEB7EA87BB7C2D199 + +Count = 775 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E5B3911E5A39F19AB + +Count = 776 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3B45BAD820B02058 + +Count = 777 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EEF6447549F63ECA2 + +Count = 778 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EFCD1661AA51FBFBA + +Count = 779 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7B4DD4E0EBD00BC3 + +Count = 780 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E3BB9AE58B72CFAEC + +Count = 781 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E041D114A2C35D19E + +Count = 782 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0ED83CD14E7FF5AA7D + +Count = 783 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E45182288D3559CF8 + +Count = 784 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E094B1793AA61EA73 + +Count = 785 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E9FB100EBEBDA0E39 + +Count = 786 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0EA7D6CE6FD76271F4 + +Count = 787 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E862B29976C90E5BF + +Count = 788 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0ED973CEB9681D52BD + +Count = 789 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E4F49EA76B38D9546 + +Count = 790 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E6B419D87E4F597A3 + +Count = 791 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E215BDC3918722FBD + +Count = 792 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E1E726B045D125D8D + +Count = 793 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760709018E833F1F5E + +Count = 794 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764074485CD66FE590 + +Count = 795 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7692608FAD176CA2AD + +Count = 796 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76FB393151EF8B3F42 + +Count = 797 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7695C5E2C19D545016 + +Count = 798 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760FC615FFB489C5BC + +Count = 799 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E760508F83AE5E0C1FA + +Count = 800 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E766350E5824917B6E0 + +Count = 801 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76F87DE2A2098DEC54 + +Count = 802 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76303B90F89947FA3E + +Count = 803 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76DB6178BF8B89A44E + +Count = 804 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76142353587A862805 + +Count = 805 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76E9A384C57A720003 + +Count = 806 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76B32C17318BBD94FA + +Count = 807 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764F5FAFAC889F21AE + +Count = 808 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76FF1816329CC2E99C + +Count = 809 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E769F64BD0F1FEDD06F + +Count = 810 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E764B454083A03E1C95 + +Count = 811 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7658F061CD9A424F8D + +Count = 812 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76DF6CD337D48DFBF4 + +Count = 813 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E769F98A98F88710ADB + +Count = 814 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76A03C169D136821A9 + +Count = 815 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E767C1DD69940A85A4A + +Count = 816 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76E139255FEC086CCF + +Count = 817 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76AD6A1044953C1A44 + +Count = 818 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E763B90073CD487FE0E + +Count = 819 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E7603F7C9B8E83F81C3 + +Count = 820 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76220A2E4053CD1588 + +Count = 821 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E767D52C96E5740A28A + +Count = 822 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EB68EDA18CD06571 + +Count = 823 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76CF609A50DBA86794 + +Count = 824 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76857ADBEE272FDF8A + +Count = 825 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76BA536CD3624FADBA + +Count = 826 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD3F2C499CD01E93B + +Count = 827 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED948F8D4B985113F5 + +Count = 828 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED469B4ABA595254C8 + +Count = 829 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2FC2F446A1B5C927 + +Count = 830 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED413E27D6D36AA673 + +Count = 831 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDDB3DD0E8FAB733D9 + +Count = 832 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD1F33D2DABDE379F + +Count = 833 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDB7AB209507294085 + +Count = 834 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2C8627B547B31A31 + +Count = 835 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDE4C055EFD7790C5B + +Count = 836 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED0F9ABDA8C5B7522B + +Count = 837 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDC0D8964F34B8DE60 + +Count = 838 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED3D5841D2344CF666 + +Count = 839 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED67D7D226C583629F + +Count = 840 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED9BA46ABBC6A1D7CB + +Count = 841 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2BE3D325D2FC1FF9 + +Count = 842 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED4B9F781851D3260A + +Count = 843 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED9FBE8594EE00EAF0 + +Count = 844 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED8C0BA4DAD47CB9E8 + +Count = 845 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED0B9716209AB30D91 + +Count = 846 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED4B636C98C64FFCBE + +Count = 847 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED74C7D38A5D56D7CC + +Count = 848 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDA8E6138E0E96AC2F + +Count = 849 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED35C2E048A2369AAA + +Count = 850 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED7991D553DB02EC21 + +Count = 851 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDEF6BC22B9AB9086B + +Count = 852 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDD70C0CAFA60177A6 + +Count = 853 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDF6F1EB571DF3E3ED + +Count = 854 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76EDA9A90C79197E54EF + +Count = 855 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED3F9328B6C2EE9314 + +Count = 856 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED1B9B5F47959691F1 + +Count = 857 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED51811EF9691129EF + +Count = 858 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED6EA8A9C42C715BDF + +Count = 859 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D60699C08C473E80 + +Count = 860 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27917BD012D917C44E + +Count = 861 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27436F17E318148373 + +Count = 862 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED272A36A91FE0F31E9C + +Count = 863 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2744CA7A8F922C71C8 + +Count = 864 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27DEC98DB1BBF1E462 + +Count = 865 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D4076074EA98E024 + +Count = 866 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27B25F7DCC466F973E + +Count = 867 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2729727AEC06F5CD8A + +Count = 868 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27E13408B6963FDBE0 + +Count = 869 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED270A6EE0F184F18590 + +Count = 870 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27C52CCB1675FE09DB + +Count = 871 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2738AC1C8B750A21DD + +Count = 872 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2762238F7F84C5B524 + +Count = 873 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED279E5037E287E70070 + +Count = 874 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED272E178E7C93BAC842 + +Count = 875 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED274E6B25411095F1B1 + +Count = 876 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED279A4AD8CDAF463D4B + +Count = 877 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2789FFF983953A6E53 + +Count = 878 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED270E634B79DBF5DA2A + +Count = 879 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED274E9731C187092B05 + +Count = 880 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED2771338ED31C100077 + +Count = 881 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27AD124ED74FD07B94 + +Count = 882 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED273036BD11E3704D11 + +Count = 883 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED277C65880A9A443B9A + +Count = 884 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27EA9F9F72DBFFDFD0 + +Count = 885 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27D2F851F6E747A01D + +Count = 886 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27F305B60E5CB53456 + +Count = 887 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27AC5D512058388354 + +Count = 888 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED273A6775EF83A844AF + +Count = 889 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED271E6F021ED4D0464A + +Count = 890 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27547543A02857FE54 + +Count = 891 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED276B5CF49D6D378C64 + +Count = 892 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA1D22EF9650CACD9F + +Count = 893 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA5A5FA644059A3751 + +Count = 894 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA884B61B5C499706C + +Count = 895 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE112DF493C7EED83 + +Count = 896 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA8FEE0CD94EA182D7 + +Count = 897 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA15EDFBE7677C177D + +Count = 898 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA1F2316223615133B + +Count = 899 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA797B0B9A9AE26421 + +Count = 900 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE2560CBADA783E95 + +Count = 901 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA2A107EE04AB228FF + +Count = 902 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAC14A96A7587C768F + +Count = 903 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0E08BD40A973FAC4 + +Count = 904 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAF3886ADDA987D2C2 + +Count = 905 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAA907F9295848463B + +Count = 906 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA557441B45B6AF36F + +Count = 907 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAE533F82A4F373B5D + +Count = 908 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA854F5317CC1802AE + +Count = 909 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA516EAE9B73CBCE54 + +Count = 910 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA42DB8FD549B79D4C + +Count = 911 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAC5473D2F07782935 + +Count = 912 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA85B347975B84D81A + +Count = 913 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FABA17F885C09DF368 + +Count = 914 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA66363881935D888B + +Count = 915 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAFB12CB473FFDBE0E + +Count = 916 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAB741FE5C46C9C885 + +Count = 917 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA21BBE92407722CCF + +Count = 918 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA19DC27A03BCA5302 + +Count = 919 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA3821C0588038C749 + +Count = 920 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA6779277684B5704B + +Count = 921 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAF14303B95F25B7B0 + +Count = 922 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAD54B7448085DB555 + +Count = 923 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA9F5135F6F4DA0D4B + +Count = 924 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FAA07882CBB1BA7F7B + +Count = 925 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF4E2AF1AD60EDADD + +Count = 926 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CB39FE6C8835E2013 + +Count = 927 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C618B2139425D672E + +Count = 928 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C08D29FC5BABAFAC1 + +Count = 929 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C662E4C55C8659595 + +Count = 930 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CFC2DBB6BE1B8003F + +Count = 931 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF6E356AEB0D10479 + +Count = 932 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C90BB4B161C267363 + +Count = 933 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C0B964C365CBC29D7 + +Count = 934 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CC3D03E6CCC763FBD + +Count = 935 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C288AD62BDEB861CD + +Count = 936 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CE7C8FDCC2FB7ED86 + +Count = 937 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C1A482A512F43C580 + +Count = 938 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C40C7B9A5DE8C5179 + +Count = 939 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CBCB40138DDAEE42D + +Count = 940 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C0CF3B8A6C9F32C1F + +Count = 941 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C6C8F139B4ADC15EC + +Count = 942 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CB8AEEE17F50FD916 + +Count = 943 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CAB1BCF59CF738A0E + +Count = 944 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2C877DA381BC3E77 + +Count = 945 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C6C73071BDD40CF58 + +Count = 946 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C53D7B8094659E42A + +Count = 947 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C8FF6780D15999FC9 + +Count = 948 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C12D28BCBB939A94C + +Count = 949 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C5E81BED0C00DDFC7 + +Count = 950 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CC87BA9A881B63B8D + +Count = 951 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CF01C672CBD0E4440 + +Count = 952 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0CD1E180D406FCD00B + +Count = 953 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C8EB967FA02716709 + +Count = 954 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C18834335D9E1A0F2 + +Count = 955 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C3C8B34C48E99A217 + +Count = 956 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C7691757A721E1A09 + +Count = 957 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C49B8C247377E6839 + +Count = 958 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E593E87D00022ED24 + +Count = 959 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E1E43CE02557217EA + +Count = 960 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2ECC5709F3947150D7 + +Count = 961 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA50EB70F6C96CD38 + +Count = 962 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2ECBF2649F1E49A26C + +Count = 963 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E51F193A1379437C6 + +Count = 964 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E5B3F7E6466FD3380 + +Count = 965 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3D6763DCCA0A449A + +Count = 966 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA64A64FC8A901E2E + +Count = 967 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E6E0C16A61A5A0844 + +Count = 968 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E8556FEE108945634 + +Count = 969 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E4A14D506F99BDA7F + +Count = 970 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EB794029BF96FF279 + +Count = 971 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EED1B916F08A06680 + +Count = 972 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E116829F20B82D3D4 + +Count = 973 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EA12F906C1FDF1BE6 + +Count = 974 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EC1533B519CF02215 + +Count = 975 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E1572C6DD2323EEEF + +Count = 976 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E06C7E793195FBDF7 + +Count = 977 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E815B55695790098E + +Count = 978 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EC1AF2FD10B6CF8A1 + +Count = 979 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EFE0B90C39075D3D3 + +Count = 980 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E222A50C7C3B5A830 + +Count = 981 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EBF0EA3016F159EB5 + +Count = 982 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EF35D961A1621E83E + +Count = 983 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E65A78162579A0C74 + +Count = 984 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E5DC04FE66B2273B9 + +Count = 985 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E7C3DA81ED0D0E7F2 + +Count = 986 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E23654F30D45D50F0 + +Count = 987 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EB55F6BFF0FCD970B + +Count = 988 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E91571C0E58B595EE + +Count = 989 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EDB4D5DB0A4322DF0 + +Count = 990 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2EE464EA8DE1525FC0 + +Count = 991 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335955C32AF45527B3 + +Count = 992 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E331E288AF8A105DD7D + +Count = 993 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33CC3C4D0960069A40 + +Count = 994 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A565F3F598E107AF + +Count = 995 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33CB992065EA3E68FB + +Count = 996 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33519AD75BC3E3FD51 + +Count = 997 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335B543A9E928AF917 + +Count = 998 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E333D0C27263E7D8E0D + +Count = 999 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A62120067EE7D4B9 + +Count = 1000 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336E67525CEE2DC2D3 + +Count = 1001 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33853DBA1BFCE39CA3 + +Count = 1002 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E334A7F91FC0DEC10E8 + +Count = 1003 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33B7FF46610D1838EE + +Count = 1004 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33ED70D595FCD7AC17 + +Count = 1005 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3311036D08FFF51943 + +Count = 1006 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33A144D496EBA8D171 + +Count = 1007 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33C1387FAB6887E882 + +Count = 1008 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3315198227D7542478 + +Count = 1009 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3306ACA369ED287760 + +Count = 1010 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3381301193A3E7C319 + +Count = 1011 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33C1C46B2BFF1B3236 + +Count = 1012 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33FE60D43964021944 + +Count = 1013 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E332241143D37C262A7 + +Count = 1014 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33BF65E7FB9B625422 + +Count = 1015 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33F336D2E0E25622A9 + +Count = 1016 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365CCC598A3EDC6E3 + +Count = 1017 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E335DAB0B1C9F55B92E + +Count = 1018 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E337C56ECE424A72D65 + +Count = 1019 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33230E0BCA202A9A67 + +Count = 1020 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33B5342F05FBBA5D9C + +Count = 1021 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33913C58F4ACC25F79 + +Count = 1022 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33DB26194A5045E767 + +Count = 1023 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33E40FAE7715259557 + +Count = 1024 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336519FC5173FEE9AC46 + +Count = 1025 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33655E8118A1ABB95688 + +Count = 1026 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658C95DF506ABA11B5 + +Count = 1027 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E5CC61AC925D8C5A + +Count = 1028 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658B30B23CE082E30E + +Count = 1029 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336511334502C95F76A4 + +Count = 1030 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33651BFDA8C7983672E2 + +Count = 1031 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33657DA5B57F34C105F8 + +Count = 1032 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E688B25F745B5F4C + +Count = 1033 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33652ECEC005E4914926 + +Count = 1034 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365C5942842F65F1756 + +Count = 1035 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33650AD603A507509B1D + +Count = 1036 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365F756D43807A4B31B + +Count = 1037 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365ADD947CCF66B27E2 + +Count = 1038 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336551AAFF51F54992B6 + +Count = 1039 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365E1ED46CFE1145A84 + +Count = 1040 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33658191EDF2623B6377 + +Count = 1041 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336555B0107EDDE8AF8D + +Count = 1042 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336546053130E794FC95 + +Count = 1043 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365C19983CAA95B48EC + +Count = 1044 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365816DF972F5A7B9C3 + +Count = 1045 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365BEC946606EBE92B1 + +Count = 1046 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336562E886643D7EE952 + +Count = 1047 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365FFCC75A291DEDFD7 + +Count = 1048 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365B39F40B9E8EAA95C + +Count = 1049 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365256557C1A9514D16 + +Count = 1050 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33651D02994595E932DB + +Count = 1051 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33653CFF7EBD2E1BA690 + +Count = 1052 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E336563A799932A961192 + +Count = 1053 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365F59DBD5CF106D669 + +Count = 1054 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365D195CAADA67ED48C + +Count = 1055 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33659B8F8B135AF96C92 + +Count = 1056 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E3365A4A63C2E1F991EA2 + +Count = 1057 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBF84220B134F3973 + +Count = 1058 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF8F96BD9461FC3BD + +Count = 1059 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E2AEDAC28871C8480 + +Count = 1060 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E43B412D47FFB196F + +Count = 1061 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E2D48C1440D24763B + +Count = 1062 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EB74B367A24F9E391 + +Count = 1063 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBD85DBBF7590E7D7 + +Count = 1064 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EDBDDC607D96790CD + +Count = 1065 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304050607 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E40F0C12799FDCA79 + +Count = 1066 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E88B6B37D0937DC13 + +Count = 1067 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506070809 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E63EC5B3A1BF98263 + +Count = 1068 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EACAE70DDEAF60E28 + +Count = 1069 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E512EA740EA02262E + +Count = 1070 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E0BA134B41BCDB2D7 + +Count = 1071 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF7D28C2918EF0783 + +Count = 1072 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E479535B70CB2CFB1 + +Count = 1073 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E27E99E8A8F9DF642 + +Count = 1074 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EF3C86306304E3AB8 + +Count = 1075 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EE07D42480A3269A0 + +Count = 1076 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E67E1F0B244FDDDD9 + +Count = 1077 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E27158A0A18012CF6 + +Count = 1078 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E18B1351883180784 + +Count = 1079 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EC490F51CD0D87C67 + +Count = 1080 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E59B406DA7C784AE2 + +Count = 1081 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E15E733C1054C3C69 + +Count = 1082 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E831D24B944F7D823 + +Count = 1083 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EBB7AEA3D784FA7EE + +Count = 1084 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E9A870DC5C3BD33A5 + +Count = 1085 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654EC5DFEAEBC73084A7 + +Count = 1086 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E53E5CE241CA0435C + +Count = 1087 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E77EDB9D54BD841B9 + +Count = 1088 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E3DF7F86BB75FF9A7 + +Count = 1089 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = C9034A2F7F9698DCB41ACCCFBF549BF747D246A868FA0E76ED27FA0C2E33654E02DE4F56F23F8B97 + diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.c b/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/api.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.c b/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.c new file mode 100644 index 0000000..770f568 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.c @@ -0,0 +1,881 @@ +/* + * 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 "elephant.h" +#include "internal-keccak.h" +#include "internal-spongent.h" +#include + +aead_cipher_t const dumbo_cipher = { + "Dumbo", + DUMBO_KEY_SIZE, + DUMBO_NONCE_SIZE, + DUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + dumbo_aead_encrypt, + dumbo_aead_decrypt +}; + +aead_cipher_t const jumbo_cipher = { + "Jumbo", + JUMBO_KEY_SIZE, + JUMBO_NONCE_SIZE, + JUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + jumbo_aead_encrypt, + jumbo_aead_decrypt +}; + +aead_cipher_t const delirium_cipher = { + "Delirium", + DELIRIUM_KEY_SIZE, + DELIRIUM_NONCE_SIZE, + DELIRIUM_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + delirium_aead_encrypt, + delirium_aead_decrypt +}; + +/** + * \brief Applies the Dumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void dumbo_lfsr + (unsigned char out[SPONGENT160_STATE_SIZE], + const unsigned char in[SPONGENT160_STATE_SIZE]) +{ + unsigned char temp = + leftRotate3_8(in[0]) ^ (in[3] << 7) ^ (in[13] >> 7); + unsigned index; + for (index = 0; index < SPONGENT160_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT160_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Dumbo. + * + * \param state Points to the Spongent-pi[160] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void dumbo_process_ad + (spongent160_state_t *state, + unsigned char mask[SPONGENT160_STATE_SIZE], + unsigned char next[SPONGENT160_STATE_SIZE], + unsigned char tag[DUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + dumbo_lfsr(next, mask); + dumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state->B, npub, DUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT160_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); + dumbo_lfsr(mask, mask); + dumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT160_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, SPONGENT160_STATE_SIZE); + + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + mlen -= SPONGENT160_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + dumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT160_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + c += temp; + } else if (*clen != DUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DUMBO_TAG_SIZE); + return 0; +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DUMBO_TAG_SIZE) + return -1; + *mlen = clen - DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DUMBO_TAG_SIZE; + while (clen >= SPONGENT160_STATE_SIZE) { + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT160_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + clen -= SPONGENT160_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Jumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void jumbo_lfsr + (unsigned char out[SPONGENT176_STATE_SIZE], + const unsigned char in[SPONGENT176_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ (in[3] << 7) ^ (in[19] >> 7); + unsigned index; + for (index = 0; index < SPONGENT176_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT176_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Jumbo. + * + * \param state Points to the Spongent-pi[170] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void jumbo_process_ad + (spongent176_state_t *state, + unsigned char mask[SPONGENT176_STATE_SIZE], + unsigned char next[SPONGENT176_STATE_SIZE], + unsigned char tag[JUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + jumbo_lfsr(next, mask); + jumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state->B, npub, JUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = JUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT176_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); + jumbo_lfsr(mask, mask); + jumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT176_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, SPONGENT176_STATE_SIZE); + + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + mlen -= SPONGENT176_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + jumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT176_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + c += temp; + } else if (*clen != JUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, JUMBO_TAG_SIZE); + return 0; +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < JUMBO_TAG_SIZE) + return -1; + *mlen = clen - JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= JUMBO_TAG_SIZE; + while (clen >= SPONGENT176_STATE_SIZE) { + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT176_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + clen -= SPONGENT176_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, JUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Delirium LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void delirium_lfsr + (unsigned char out[KECCAKP_200_STATE_SIZE], + const unsigned char in[KECCAKP_200_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ leftRotate1_8(in[2]) ^ (in[13] << 1); + unsigned index; + for (index = 0; index < KECCAKP_200_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[KECCAKP_200_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Delirium. + * + * \param state Points to the Keccak[200] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void delirium_process_ad + (keccakp_200_state_t *state, + unsigned char mask[KECCAKP_200_STATE_SIZE], + unsigned char next[KECCAKP_200_STATE_SIZE], + unsigned char tag[DELIRIUM_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + delirium_lfsr(next, mask); + delirium_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state->B, npub, DELIRIUM_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DELIRIUM_NONCE_SIZE; + while (adlen > 0) { + size = KECCAKP_200_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); + delirium_lfsr(mask, mask); + delirium_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= KECCAKP_200_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, KECCAKP_200_STATE_SIZE); + + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + mlen -= KECCAKP_200_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + delirium_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, KECCAKP_200_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + c += temp; + } else if (*clen != DELIRIUM_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DELIRIUM_TAG_SIZE); + return 0; +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char *mtemp = m; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DELIRIUM_TAG_SIZE) + return -1; + *mlen = clen - DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DELIRIUM_TAG_SIZE; + while (clen >= KECCAKP_200_STATE_SIZE) { + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, KECCAKP_200_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + clen -= KECCAKP_200_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DELIRIUM_TAG_SIZE); +} diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.h new file mode 100644 index 0000000..f775e3d --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/elephant.h @@ -0,0 +1,291 @@ +/* + * 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_ELEPHANT_H +#define LWCRYPTO_ELEPHANT_H + +#include "aead-common.h" + +/** + * \file elephant.h + * \brief Elephant authenticated encryption algorithm family. + * + * Elephant is a family of authenticated encryption algorithms based + * around the Spongent-pi and Keccak permutations. + * + * \li Dumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[160] permutation. This is + * the primary member of the family. + * \li Jumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[176] permutation. + * \li Delirium has a 128-bit key, a 96-bit nonce, and a 128-bit authentication + * tag. It is based around the Keccak[200] permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Dumbo. + */ +#define DUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Dumbo. + */ +#define DUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Dumbo. + */ +#define DUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Jumbo. + */ +#define JUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Jumbo. + */ +#define JUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Jumbo. + */ +#define JUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Delirium. + */ +#define DELIRIUM_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Delirium. + */ +#define DELIRIUM_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Delirium. + */ +#define DELIRIUM_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Dumbo cipher. + */ +extern aead_cipher_t const dumbo_cipher; + +/** + * \brief Meta-information block for the Jumbo cipher. + */ +extern aead_cipher_t const jumbo_cipher; + +/** + * \brief Meta-information block for the Delirium cipher. + */ +extern aead_cipher_t const delirium_cipher; + +/** + * \brief Encrypts and authenticates a packet with Dumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa dumbo_aead_decrypt() + */ +int dumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Dumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa dumbo_aead_encrypt() + */ +int dumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Jumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa jumbo_aead_decrypt() + */ +int jumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Jumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa jumbo_aead_encrypt() + */ +int jumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Delirium. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa delirium_aead_decrypt() + */ +int delirium_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); + +/** + * \brief Decrypts and authenticates a packet with Delirium. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa delirium_aead_encrypt() + */ +int delirium_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/encrypt.c b/elephant/Implementations/crypto_aead/elephant160v1/rhys/encrypt.c new file mode 100644 index 0000000..df2a4b5 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "elephant.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 dumbo_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 dumbo_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.c b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.c b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.c new file mode 100644 index 0000000..69a8ecb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.c @@ -0,0 +1,346 @@ +/* + * 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 "internal-spongent.h" + +/** + * \brief Applies the Spongent-pi S-box in parallel to the 8 nibbles + * of a 32-bit word. + * + * \param x3 The input values to the parallel S-boxes. + * + * \return The output values from the parallel S-boxes. + * + * Based on the bit-sliced S-box implementation from here: + * https://github.com/DadaIsCrazy/usuba/blob/master/data/sboxes/spongent.ua + * + * Note that spongent.ua numbers bits from highest to lowest, so x0 is the + * high bit of each nibble and x3 is the low bit. + */ +static uint32_t spongent_sbox(uint32_t x3) +{ + uint32_t q0, q1, q2, q3, t0, t1, t2, t3; + uint32_t x2 = (x3 >> 1); + uint32_t x1 = (x2 >> 1); + uint32_t x0 = (x1 >> 1); + q0 = x0 ^ x2; + q1 = x1 ^ x2; + t0 = q0 & q1; + q2 = ~(x0 ^ x1 ^ x3 ^ t0); + t1 = q2 & ~x0; + q3 = x1 ^ t1; + t2 = q3 & (q3 ^ x2 ^ x3 ^ t0); + t3 = (x2 ^ t0) & ~(x1 ^ t0); + q0 = x1 ^ x2 ^ x3 ^ t2; + q1 = x0 ^ x2 ^ x3 ^ t0 ^ t1; + q2 = x0 ^ x1 ^ x2 ^ t1; + q3 = x0 ^ x3 ^ t0 ^ t3; + return ((q0 << 3) & 0x88888888U) | ((q1 << 2) & 0x44444444U) | + ((q2 << 1) & 0x22222222U) | (q3 & 0x11111111U); +} + +void spongent160_permute(spongent160_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[160] */ + 0x75, 0xae, 0x6a, 0x56, 0x54, 0x2a, 0x29, 0x94, + 0x53, 0xca, 0x27, 0xe4, 0x4f, 0xf2, 0x1f, 0xf8, + 0x3e, 0x7c, 0x7d, 0xbe, 0x7a, 0x5e, 0x74, 0x2e, + 0x68, 0x16, 0x50, 0x0a, 0x21, 0x84, 0x43, 0xc2, + 0x07, 0xe0, 0x0e, 0x70, 0x1c, 0x38, 0x38, 0x1c, + 0x71, 0x8e, 0x62, 0x46, 0x44, 0x22, 0x09, 0x90, + 0x12, 0x48, 0x24, 0x24, 0x49, 0x92, 0x13, 0xc8, + 0x26, 0x64, 0x4d, 0xb2, 0x1b, 0xd8, 0x36, 0x6c, + 0x6d, 0xb6, 0x5a, 0x5a, 0x35, 0xac, 0x6b, 0xd6, + 0x56, 0x6a, 0x2d, 0xb4, 0x5b, 0xda, 0x37, 0xec, + 0x6f, 0xf6, 0x5e, 0x7a, 0x3d, 0xbc, 0x7b, 0xde, + 0x76, 0x6e, 0x6c, 0x36, 0x58, 0x1a, 0x31, 0x8c, + 0x63, 0xc6, 0x46, 0x62, 0x0d, 0xb0, 0x1a, 0x58, + 0x34, 0x2c, 0x69, 0x96, 0x52, 0x4a, 0x25, 0xa4, + 0x4b, 0xd2, 0x17, 0xe8, 0x2e, 0x74, 0x5d, 0xba, + 0x3b, 0xdc, 0x77, 0xee, 0x6e, 0x76, 0x5c, 0x3a, + 0x39, 0x9c, 0x73, 0xce, 0x66, 0x66, 0x4c, 0x32, + 0x19, 0x98, 0x32, 0x4c, 0x65, 0xa6, 0x4a, 0x52, + 0x15, 0xa8, 0x2a, 0x54, 0x55, 0xaa, 0x2b, 0xd4, + 0x57, 0xea, 0x2f, 0xf4, 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4; + uint32_t t0, t1, t2, t3, t4; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); +#endif + + /* Perform the 80 rounds of Spongent-pi[160] */ + for (round = 0; round < 80; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x4 ^= ((uint32_t)(rc[1])) << 24; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + + /* Permute the bits of the state. Bit i is moved to (40 * i) % 159 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + #define BCP(x, bit) ((x) & (((uint32_t)1) << (bit))) + #define BUP(x, from, to) \ + (((x) << ((to) - (from))) & (((uint32_t)1) << (to))) + #define BDN(x, from, to) \ + (((x) >> ((from) - (to))) & (((uint32_t)1) << (to))) + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 8) ^ BUP(t0, 5, 9) ^ BUP(t0, 9, 10) ^ + BDN(t0, 13, 11) ^ BDN(t0, 17, 12) ^ BDN(t0, 21, 13) ^ + BDN(t0, 25, 14) ^ BDN(t0, 29, 15) ^ BUP(t1, 1, 16) ^ + BUP(t1, 5, 17) ^ BUP(t1, 9, 18) ^ BUP(t1, 13, 19) ^ + BUP(t1, 17, 20) ^ BCP(t1, 21) ^ BDN(t1, 25, 22) ^ + BDN(t1, 29, 23) ^ BUP(t2, 1, 24) ^ BUP(t2, 5, 25) ^ + BUP(t2, 9, 26) ^ BUP(t2, 13, 27) ^ BUP(t2, 17, 28) ^ + BUP(t2, 21, 29) ^ BUP(t2, 25, 30) ^ BUP(t2, 29, 31) ^ + BCP(t4, 0) ^ BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ + BDN(t4, 12, 3) ^ BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ + BDN(t4, 24, 6) ^ BDN(t4, 28, 7); + x2 = BUP(t0, 2, 16) ^ BUP(t0, 6, 17) ^ BUP(t0, 10, 18) ^ + BUP(t0, 14, 19) ^ BUP(t0, 18, 20) ^ BDN(t0, 22, 21) ^ + BDN(t0, 26, 22) ^ BDN(t0, 30, 23) ^ BUP(t1, 2, 24) ^ + BUP(t1, 6, 25) ^ BUP(t1, 10, 26) ^ BUP(t1, 14, 27) ^ + BUP(t1, 18, 28) ^ BUP(t1, 22, 29) ^ BUP(t1, 26, 30) ^ + BUP(t1, 30, 31) ^ BDN(t3, 1, 0) ^ BDN(t3, 5, 1) ^ + BDN(t3, 9, 2) ^ BDN(t3, 13, 3) ^ BDN(t3, 17, 4) ^ + BDN(t3, 21, 5) ^ BDN(t3, 25, 6) ^ BDN(t3, 29, 7) ^ + BUP(t4, 1, 8) ^ BUP(t4, 5, 9) ^ BUP(t4, 9, 10) ^ + BDN(t4, 13, 11) ^ BDN(t4, 17, 12) ^ BDN(t4, 21, 13) ^ + BDN(t4, 25, 14) ^ BDN(t4, 29, 15); + x3 = BUP(t0, 3, 24) ^ BUP(t0, 7, 25) ^ BUP(t0, 11, 26) ^ + BUP(t0, 15, 27) ^ BUP(t0, 19, 28) ^ BUP(t0, 23, 29) ^ + BUP(t0, 27, 30) ^ BCP(t0, 31) ^ BDN(t2, 2, 0) ^ + BDN(t2, 6, 1) ^ BDN(t2, 10, 2) ^ BDN(t2, 14, 3) ^ + BDN(t2, 18, 4) ^ BDN(t2, 22, 5) ^ BDN(t2, 26, 6) ^ + BDN(t2, 30, 7) ^ BUP(t3, 2, 8) ^ BUP(t3, 6, 9) ^ + BCP(t3, 10) ^ BDN(t3, 14, 11) ^ BDN(t3, 18, 12) ^ + BDN(t3, 22, 13) ^ BDN(t3, 26, 14) ^ BDN(t3, 30, 15) ^ + BUP(t4, 2, 16) ^ BUP(t4, 6, 17) ^ BUP(t4, 10, 18) ^ + BUP(t4, 14, 19) ^ BUP(t4, 18, 20) ^ BDN(t4, 22, 21) ^ + BDN(t4, 26, 22) ^ BDN(t4, 30, 23); + x4 = BDN(t1, 3, 0) ^ BDN(t1, 7, 1) ^ BDN(t1, 11, 2) ^ + BDN(t1, 15, 3) ^ BDN(t1, 19, 4) ^ BDN(t1, 23, 5) ^ + BDN(t1, 27, 6) ^ BDN(t1, 31, 7) ^ BUP(t2, 3, 8) ^ + BUP(t2, 7, 9) ^ BDN(t2, 11, 10) ^ BDN(t2, 15, 11) ^ + BDN(t2, 19, 12) ^ BDN(t2, 23, 13) ^ BDN(t2, 27, 14) ^ + BDN(t2, 31, 15) ^ BUP(t3, 3, 16) ^ BUP(t3, 7, 17) ^ + BUP(t3, 11, 18) ^ BUP(t3, 15, 19) ^ BUP(t3, 19, 20) ^ + BDN(t3, 23, 21) ^ BDN(t3, 27, 22) ^ BDN(t3, 31, 23) ^ + BUP(t4, 3, 24) ^ BUP(t4, 7, 25) ^ BUP(t4, 11, 26) ^ + BUP(t4, 15, 27) ^ BUP(t4, 19, 28) ^ BUP(t4, 23, 29) ^ + BUP(t4, 27, 30) ^ BCP(t4, 31); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); +#endif +} + +void spongent176_permute(spongent176_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[176] */ + 0x45, 0xa2, 0x0b, 0xd0, 0x16, 0x68, 0x2c, 0x34, + 0x59, 0x9a, 0x33, 0xcc, 0x67, 0xe6, 0x4e, 0x72, + 0x1d, 0xb8, 0x3a, 0x5c, 0x75, 0xae, 0x6a, 0x56, + 0x54, 0x2a, 0x29, 0x94, 0x53, 0xca, 0x27, 0xe4, + 0x4f, 0xf2, 0x1f, 0xf8, 0x3e, 0x7c, 0x7d, 0xbe, + 0x7a, 0x5e, 0x74, 0x2e, 0x68, 0x16, 0x50, 0x0a, + 0x21, 0x84, 0x43, 0xc2, 0x07, 0xe0, 0x0e, 0x70, + 0x1c, 0x38, 0x38, 0x1c, 0x71, 0x8e, 0x62, 0x46, + 0x44, 0x22, 0x09, 0x90, 0x12, 0x48, 0x24, 0x24, + 0x49, 0x92, 0x13, 0xc8, 0x26, 0x64, 0x4d, 0xb2, + 0x1b, 0xd8, 0x36, 0x6c, 0x6d, 0xb6, 0x5a, 0x5a, + 0x35, 0xac, 0x6b, 0xd6, 0x56, 0x6a, 0x2d, 0xb4, + 0x5b, 0xda, 0x37, 0xec, 0x6f, 0xf6, 0x5e, 0x7a, + 0x3d, 0xbc, 0x7b, 0xde, 0x76, 0x6e, 0x6c, 0x36, + 0x58, 0x1a, 0x31, 0x8c, 0x63, 0xc6, 0x46, 0x62, + 0x0d, 0xb0, 0x1a, 0x58, 0x34, 0x2c, 0x69, 0x96, + 0x52, 0x4a, 0x25, 0xa4, 0x4b, 0xd2, 0x17, 0xe8, + 0x2e, 0x74, 0x5d, 0xba, 0x3b, 0xdc, 0x77, 0xee, + 0x6e, 0x76, 0x5c, 0x3a, 0x39, 0x9c, 0x73, 0xce, + 0x66, 0x66, 0x4c, 0x32, 0x19, 0x98, 0x32, 0x4c, + 0x65, 0xa6, 0x4a, 0x52, 0x15, 0xa8, 0x2a, 0x54, + 0x55, 0xaa, 0x2b, 0xd4, 0x57, 0xea, 0x2f, 0xf4, + 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t t0, t1, t2, t3, t4, t5; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; + x5 = state->W[5]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); + x5 = le_load_word16(state->B + 20); /* Last word is only 16 bits */ +#endif + + /* Perform the 90 rounds of Spongent-pi[176] */ + for (round = 0; round < 90; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x5 ^= ((uint32_t)(rc[1])) << 8; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + t5 = spongent_sbox(x5); + + /* Permute the bits of the state. Bit i is moved to (44 * i) % 175 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 12) ^ BUP(t0, 5, 13) ^ BUP(t0, 9, 14) ^ + BUP(t0, 13, 15) ^ BDN(t0, 17, 16) ^ BDN(t0, 21, 17) ^ + BDN(t0, 25, 18) ^ BDN(t0, 29, 19) ^ BUP(t1, 1, 20) ^ + BUP(t1, 5, 21) ^ BUP(t1, 9, 22) ^ BUP(t1, 13, 23) ^ + BUP(t1, 17, 24) ^ BUP(t1, 21, 25) ^ BUP(t1, 25, 26) ^ + BDN(t1, 29, 27) ^ BUP(t2, 1, 28) ^ BUP(t2, 5, 29) ^ + BUP(t2, 9, 30) ^ BUP(t2, 13, 31) ^ BCP(t4, 0) ^ + BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ BDN(t4, 12, 3) ^ + BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ BDN(t4, 24, 6) ^ + BDN(t4, 28, 7) ^ BUP(t5, 0, 8) ^ BUP(t5, 4, 9) ^ + BUP(t5, 8, 10) ^ BDN(t5, 12, 11); + x2 = BUP(t0, 2, 24) ^ BUP(t0, 6, 25) ^ BUP(t0, 10, 26) ^ + BUP(t0, 14, 27) ^ BUP(t0, 18, 28) ^ BUP(t0, 22, 29) ^ + BUP(t0, 26, 30) ^ BUP(t0, 30, 31) ^ BDN(t2, 17, 0) ^ + BDN(t2, 21, 1) ^ BDN(t2, 25, 2) ^ BDN(t2, 29, 3) ^ + BUP(t3, 1, 4) ^ BCP(t3, 5) ^ BDN(t3, 9, 6) ^ + BDN(t3, 13, 7) ^ BDN(t3, 17, 8) ^ BDN(t3, 21, 9) ^ + BDN(t3, 25, 10) ^ BDN(t3, 29, 11) ^ BUP(t4, 1, 12) ^ + BUP(t4, 5, 13) ^ BUP(t4, 9, 14) ^ BUP(t4, 13, 15) ^ + BDN(t4, 17, 16) ^ BDN(t4, 21, 17) ^ BDN(t4, 25, 18) ^ + BDN(t4, 29, 19) ^ BUP(t5, 1, 20) ^ BUP(t5, 5, 21) ^ + BUP(t5, 9, 22) ^ BUP(t5, 13, 23); + x3 = BDN(t1, 2, 0) ^ BDN(t1, 6, 1) ^ BDN(t1, 10, 2) ^ + BDN(t1, 14, 3) ^ BDN(t1, 18, 4) ^ BDN(t1, 22, 5) ^ + BDN(t1, 26, 6) ^ BDN(t1, 30, 7) ^ BUP(t2, 2, 8) ^ + BUP(t2, 6, 9) ^ BCP(t2, 10) ^ BDN(t2, 14, 11) ^ + BDN(t2, 18, 12) ^ BDN(t2, 22, 13) ^ BDN(t2, 26, 14) ^ + BDN(t2, 30, 15) ^ BUP(t3, 2, 16) ^ BUP(t3, 6, 17) ^ + BUP(t3, 10, 18) ^ BUP(t3, 14, 19) ^ BUP(t3, 18, 20) ^ + BDN(t3, 22, 21) ^ BDN(t3, 26, 22) ^ BDN(t3, 30, 23) ^ + BUP(t4, 2, 24) ^ BUP(t4, 6, 25) ^ BUP(t4, 10, 26) ^ + BUP(t4, 14, 27) ^ BUP(t4, 18, 28) ^ BUP(t4, 22, 29) ^ + BUP(t4, 26, 30) ^ BUP(t4, 30, 31); + x4 = BUP(t0, 3, 4) ^ BDN(t0, 7, 5) ^ BDN(t0, 11, 6) ^ + BDN(t0, 15, 7) ^ BDN(t0, 19, 8) ^ BDN(t0, 23, 9) ^ + BDN(t0, 27, 10) ^ BDN(t0, 31, 11) ^ BUP(t1, 3, 12) ^ + BUP(t1, 7, 13) ^ BUP(t1, 11, 14) ^ BCP(t1, 15) ^ + BDN(t1, 19, 16) ^ BDN(t1, 23, 17) ^ BDN(t1, 27, 18) ^ + BDN(t1, 31, 19) ^ BUP(t2, 3, 20) ^ BUP(t2, 7, 21) ^ + BUP(t2, 11, 22) ^ BUP(t2, 15, 23) ^ BUP(t2, 19, 24) ^ + BUP(t2, 23, 25) ^ BDN(t2, 27, 26) ^ BDN(t2, 31, 27) ^ + BUP(t3, 3, 28) ^ BUP(t3, 7, 29) ^ BUP(t3, 11, 30) ^ + BUP(t3, 15, 31) ^ BDN(t5, 2, 0) ^ BDN(t5, 6, 1) ^ + BDN(t5, 10, 2) ^ BDN(t5, 14, 3); + x5 = BDN(t3, 19, 0) ^ BDN(t3, 23, 1) ^ BDN(t3, 27, 2) ^ + BDN(t3, 31, 3) ^ BUP(t4, 3, 4) ^ BDN(t4, 7, 5) ^ + BDN(t4, 11, 6) ^ BDN(t4, 15, 7) ^ BDN(t4, 19, 8) ^ + BDN(t4, 23, 9) ^ BDN(t4, 27, 10) ^ BDN(t4, 31, 11) ^ + BUP(t5, 3, 12) ^ BUP(t5, 7, 13) ^ BUP(t5, 11, 14) ^ + BCP(t5, 15); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; + state->W[5] = x5; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); + le_store_word16(state->B + 20, x5); /* Last word is only 16 bits */ +#endif +} diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.h new file mode 100644 index 0000000..bb9823f --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-spongent.h @@ -0,0 +1,91 @@ +/* + * 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_SPONGENT_H +#define LW_INTERNAL_SPONGENT_H + +#include "internal-util.h" + +/** + * \file internal-spongent.h + * \brief Internal implementation of the Spongent-pi permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the Spongent-pi[160] state in bytes. + */ +#define SPONGENT160_STATE_SIZE 20 + +/** + * \brief Size of the Spongent-pi[176] state in bytes. + */ +#define SPONGENT176_STATE_SIZE 22 + +/** + * \brief Structure of the internal state of the Spongent-pi[160] permutation. + */ +typedef union +{ + uint32_t W[5]; /**< Spongent-pi[160] state as 32-bit words */ + uint8_t B[20]; /**< Spongent-pi[160] state as bytes */ + +} spongent160_state_t; + +/** + * \brief Structure of the internal state of the Spongent-pi[176] permutation. + * + * Note: The state is technically only 176 bits, but we increase it to + * 192 bits so that we can use 32-bit word operations to manipulate the + * state. The extra bits in the last word are fixed to zero. + */ +typedef union +{ + uint32_t W[6]; /**< Spongent-pi[176] state as 32-bit words */ + uint8_t B[24]; /**< Spongent-pi[176] state as bytes */ + +} spongent176_state_t; + +/** + * \brief Permutes the Spongent-pi[160] state. + * + * \param state The Spongent-pi[160] state to be permuted. + */ +void spongent160_permute(spongent160_state_t *state); + +/** + * \brief Permutes the Spongent-pi[176] state. + * + * \param state The Spongent-pi[176] state to be permuted. + */ +void spongent176_permute(spongent176_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-util.h b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant160v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant176v1/LWC_AEAD_KAT_128_96.txt b/elephant/Implementations/crypto_aead/elephant176v1/LWC_AEAD_KAT_128_96.txt index 6b167cf..3069a6b 100644 --- a/elephant/Implementations/crypto_aead/elephant176v1/LWC_AEAD_KAT_128_96.txt +++ b/elephant/Implementations/crypto_aead/elephant176v1/LWC_AEAD_KAT_128_96.txt @@ -1,7623 +1,7623 @@ -Count = 1 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = -CT = F9F52C3201D8EE81 - -Count = 2 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00 -CT = 56F0058E7C78EC2C - -Count = 3 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001 -CT = 79E9C6803C3417AD - -Count = 4 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102 -CT = 768E1F200B61C076 - -Count = 5 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203 -CT = DBC152B6ED0F8634 - -Count = 6 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304 -CT = 1564ED2EB9783366 - -Count = 7 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405 -CT = 5CE812FA41D357CF - -Count = 8 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506 -CT = FDE915DD1AD241D0 - -Count = 9 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304050607 -CT = 717CDC35B10DC35A - -Count = 10 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708 -CT = B9A245343D21BFF2 - -Count = 11 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506070809 -CT = 32A19787FF322F01 - -Count = 12 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A -CT = 74980ABB12C52562 - -Count = 13 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B -CT = 2E7A838B88A44924 - -Count = 14 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C -CT = D16E817692F67CF0 - -Count = 15 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D -CT = 961A4476E4552DB7 - -Count = 16 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E -CT = 2740B55EDFD9D4E3 - -Count = 17 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F -CT = E792EFD2456C6D1E - -Count = 18 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10 -CT = B04E2CAD1EE58029 - -Count = 19 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 72E6D9BD17795BB5 - -Count = 20 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 83A4F4BC8C32A7E7 - -Count = 21 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 50694A2CD9343BB4 - -Count = 22 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = F0C0DAEFE18C6BFD - -Count = 23 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 406A6DC888A7B6B5 - -Count = 24 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 6A8549B20113B476 - -Count = 25 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = B7EFECA8ADD9CA53 - -Count = 26 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 4A894B808287767A - -Count = 27 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 93D71398484A7585 - -Count = 28 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 235A7E11AB5A2FE2 - -Count = 29 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 91C231087BF2FEC6 - -Count = 30 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 488B52477EC7A91B - -Count = 31 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 8EFC1861083FD51E - -Count = 32 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 7BAB5FC020140241 - -Count = 33 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = BC8A4531026641A2 - -Count = 34 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = -CT = FE2C92E25CDDEBE2A5 - -Count = 35 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00 -CT = FE8397CBE0A04BE008 - -Count = 36 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001 -CT = FEAC8E08EEE0071B89 - -Count = 37 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102 -CT = FEA3E9D14ED752CC52 - -Count = 38 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203 -CT = FE0EA69CD8313C8A10 - -Count = 39 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304 -CT = FEC0032340654B3F42 - -Count = 40 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405 -CT = FE898FDC949DE05BEB - -Count = 41 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506 -CT = FE288EDBB3C6E14DF4 - -Count = 42 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304050607 -CT = FEA41B125B6D3ECF7E - -Count = 43 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708 -CT = FE6CC58B5AE112B3D6 - -Count = 44 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506070809 -CT = FEE7C659E923012325 - -Count = 45 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A -CT = FEA1FFC4D5CEF62946 - -Count = 46 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B -CT = FEFB1D4DE554974500 - -Count = 47 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C -CT = FE04094F184EC570D4 - -Count = 48 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D -CT = FE437D8A1838662193 - -Count = 49 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E -CT = FEF2277B3003EAD8C7 - -Count = 50 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F -CT = FE32F521BC995F613A - -Count = 51 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FE6529E2C3C2D68C0D - -Count = 52 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEA78117D3CB4A5791 - -Count = 53 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FE56C33AD25001ABC3 - -Count = 54 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FE850E844205073790 - -Count = 55 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FE25A714813DBF67D9 - -Count = 56 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FE950DA3A65494BA91 - -Count = 57 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEBFE287DCDD20B852 - -Count = 58 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FE628822C671EAC677 - -Count = 59 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FE9FEE85EE5EB47A5E - -Count = 60 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FE46B0DDF6947979A1 - -Count = 61 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEF63DB07F776923C6 - -Count = 62 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FE44A5FF66A7C1F2E2 - -Count = 63 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FE9DEC9C29A2F4A53F - -Count = 64 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FE5B9BD60FD40CD93A - -Count = 65 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEAECC91AEFC270E65 - -Count = 66 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FE69ED8B5FDE554D86 - -Count = 67 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = -CT = FEC9C5D02385265671AA - -Count = 68 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00 -CT = FEC96AD50A395BF67307 - -Count = 69 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001 -CT = FEC945CCC9371BBA8886 - -Count = 70 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102 -CT = FEC94AAB10972CEF5F5D - -Count = 71 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203 -CT = FEC9E7E45D01CA81191F - -Count = 72 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304 -CT = FEC92941E2999EF6AC4D - -Count = 73 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405 -CT = FEC960CD1D4D665DC8E4 - -Count = 74 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506 -CT = FEC9C1CC1A6A3D5CDEFB - -Count = 75 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304050607 -CT = FEC94D59D38296835C71 - -Count = 76 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708 -CT = FEC985874A831AAF20D9 - -Count = 77 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506070809 -CT = FEC90E849830D8BCB02A - -Count = 78 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A -CT = FEC948BD050C354BBA49 - -Count = 79 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B -CT = FEC9125F8C3CAF2AD60F - -Count = 80 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C -CT = FEC9ED4B8EC1B578E3DB - -Count = 81 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D -CT = FEC9AA3F4BC1C3DBB29C - -Count = 82 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E -CT = FEC91B65BAE9F8574BC8 - -Count = 83 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC9DBB7E06562E2F235 - -Count = 84 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC98C6B231A396B1F02 - -Count = 85 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC94EC3D60A30F7C49E - -Count = 86 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC9BF81FB0BABBC38CC - -Count = 87 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC96C4C459BFEBAA49F - -Count = 88 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC9CCE5D558C602F4D6 - -Count = 89 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC97C4F627FAF29299E - -Count = 90 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC956A04605269D2B5D - -Count = 91 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC98BCAE31F8A575578 - -Count = 92 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC976AC4437A509E951 - -Count = 93 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC9AFF21C2F6FC4EAAE - -Count = 94 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC91F7F71A68CD4B0C9 - -Count = 95 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC9ADE73EBF5C7C61ED - -Count = 96 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC974AE5DF059493630 - -Count = 97 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC9B2D917D62FB14A35 - -Count = 98 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC9478E5077079A9D6A - -Count = 99 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC980AF4A8625E8DE89 - -Count = 100 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = -CT = FEC9411BC7AA32DC76BB7D - -Count = 101 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00 -CT = FEC941B4C2838EA1D6B9D0 - -Count = 102 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001 -CT = FEC9419BDB4080E19A4251 - -Count = 103 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102 -CT = FEC94194BC9920D6CF958A - -Count = 104 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203 -CT = FEC94139F3D4B630A1D3C8 - -Count = 105 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304 -CT = FEC941F7566B2E64D6669A - -Count = 106 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405 -CT = FEC941BEDA94FA9C7D0233 - -Count = 107 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506 -CT = FEC9411FDB93DDC77C142C - -Count = 108 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304050607 -CT = FEC941934E5A356CA396A6 - -Count = 109 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708 -CT = FEC9415B90C334E08FEA0E - -Count = 110 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506070809 -CT = FEC941D0931187229C7AFD - -Count = 111 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A -CT = FEC94196AA8CBBCF6B709E - -Count = 112 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B -CT = FEC941CC48058B550A1CD8 - -Count = 113 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C -CT = FEC941335C07764F58290C - -Count = 114 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D -CT = FEC9417428C27639FB784B - -Count = 115 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941C572335E0277811F - -Count = 116 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC94105A069D298C238E2 - -Count = 117 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941527CAAADC34BD5D5 - -Count = 118 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC94190D45FBDCAD70E49 - -Count = 119 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941619672BC519CF21B - -Count = 120 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941B25BCC2C049A6E48 - -Count = 121 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC94112F25CEF3C223E01 - -Count = 122 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941A258EBC85509E349 - -Count = 123 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC94188B7CFB2DCBDE18A - -Count = 124 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC94155DD6AA870779FAF - -Count = 125 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941A8BBCD805F292386 - -Count = 126 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC94171E5959895E42079 - -Count = 127 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941C168F81176F47A1E - -Count = 128 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC94173F0B708A65CAB3A - -Count = 129 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941AAB9D447A369FCE7 - -Count = 130 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC9416CCE9E61D59180E2 - -Count = 131 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC9419999D9C0FDBA57BD - -Count = 132 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC9415EB8C331DFC8145E - -Count = 133 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = -CT = FEC941479E83007EEF580F5C - -Count = 134 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00 -CT = FEC94147318629C292F80DF1 - -Count = 135 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001 -CT = FEC941471E9FEACCD2B4F670 - -Count = 136 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102 -CT = FEC9414711F8336CE5E121AB - -Count = 137 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203 -CT = FEC94147BCB77EFA038F67E9 - -Count = 138 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304 -CT = FEC941477212C16257F8D2BB - -Count = 139 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405 -CT = FEC941473B9E3EB6AF53B612 - -Count = 140 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506 -CT = FEC941479A9F3991F452A00D - -Count = 141 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304050607 -CT = FEC94147160AF0795F8D2287 - -Count = 142 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708 -CT = FEC94147DED46978D3A15E2F - -Count = 143 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506070809 -CT = FEC9414755D7BBCB11B2CEDC - -Count = 144 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A -CT = FEC9414713EE26F7FC45C4BF - -Count = 145 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B -CT = FEC94147490CAFC76624A8F9 - -Count = 146 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C -CT = FEC94147B618AD3A7C769D2D - -Count = 147 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D -CT = FEC94147F16C683A0AD5CC6A - -Count = 148 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E -CT = FEC94147403699123159353E - -Count = 149 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC9414780E4C39EABEC8CC3 - -Count = 150 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC94147D73800E1F06561F4 - -Count = 151 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941471590F5F1F9F9BA68 - -Count = 152 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC94147E4D2D8F062B2463A - -Count = 153 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC94147371F666037B4DA69 - -Count = 154 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC9414797B6F6A30F0C8A20 - -Count = 155 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC94147271C418466275768 - -Count = 156 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470DF365FEEF9355AB - -Count = 157 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC94147D099C0E443592B8E - -Count = 158 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941472DFF67CC6C0797A7 - -Count = 159 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC94147F4A13FD4A6CA9458 - -Count = 160 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC94147442C525D45DACE3F - -Count = 161 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC94147F6B41D4495721F1B - -Count = 162 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941472FFD7E0B904748C6 - -Count = 163 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC94147E98A342DE6BF34C3 - -Count = 164 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941471CDD738CCE94E39C - -Count = 165 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC94147DBFC697DECE6A07F - -Count = 166 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = -CT = FEC941470C278F4DD8B1E42763 - -Count = 167 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00 -CT = FEC941470C888A6464CC4425CE - -Count = 168 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001 -CT = FEC941470CA793A76A8C08DE4F - -Count = 169 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102 -CT = FEC941470CA8F47ECABB5D0994 - -Count = 170 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203 -CT = FEC941470C05BB335C5D334FD6 - -Count = 171 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304 -CT = FEC941470CCB1E8CC40944FA84 - -Count = 172 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405 -CT = FEC941470C82927310F1EF9E2D - -Count = 173 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506 -CT = FEC941470C23937437AAEE8832 - -Count = 174 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304050607 -CT = FEC941470CAF06BDDF01310AB8 - -Count = 175 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708 -CT = FEC941470C67D824DE8D1D7610 - -Count = 176 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506070809 -CT = FEC941470CECDBF66D4F0EE6E3 - -Count = 177 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A -CT = FEC941470CAAE26B51A2F9EC80 - -Count = 178 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B -CT = FEC941470CF000E261389880C6 - -Count = 179 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C -CT = FEC941470C0F14E09C22CAB512 - -Count = 180 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D -CT = FEC941470C4860259C5469E455 - -Count = 181 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CF93AD4B46FE51D01 - -Count = 182 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470C39E88E38F550A4FC - -Count = 183 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470C6E344D47AED949CB - -Count = 184 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CAC9CB857A7459257 - -Count = 185 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470C5DDE95563C0E6E05 - -Count = 186 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470C8E132BC66908F256 - -Count = 187 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470C2EBABB0551B0A21F - -Count = 188 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470C9E100C22389B7F57 - -Count = 189 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB4FF2858B12F7D94 - -Count = 190 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470C69958D421DE503B1 - -Count = 191 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470C94F32A6A32BBBF98 - -Count = 192 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470C4DAD7272F876BC67 - -Count = 193 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CFD201FFB1B66E600 - -Count = 194 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470C4FB850E2CBCE3724 - -Count = 195 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470C96F133ADCEFB60F9 - -Count = 196 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470C5086798BB8031CFC - -Count = 197 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CA5D13E2A9028CBA3 - -Count = 198 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470C62F024DBB25A8840 - -Count = 199 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = -CT = FEC941470CB8E24205EEF8093C08 - -Count = 200 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00 -CT = FEC941470CB84D472C5285A93EA5 - -Count = 201 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001 -CT = FEC941470CB8625EEF5CC5E5C524 - -Count = 202 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102 -CT = FEC941470CB86D3936FCF2B012FF - -Count = 203 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203 -CT = FEC941470CB8C0767B6A14DE54BD - -Count = 204 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304 -CT = FEC941470CB80ED3C4F240A9E1EF - -Count = 205 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405 -CT = FEC941470CB8475F3B26B8028546 - -Count = 206 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506 -CT = FEC941470CB8E65E3C01E3039359 - -Count = 207 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304050607 -CT = FEC941470CB86ACBF5E948DC11D3 - -Count = 208 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708 -CT = FEC941470CB8A2156CE8C4F06D7B - -Count = 209 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506070809 -CT = FEC941470CB82916BE5B06E3FD88 - -Count = 210 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A -CT = FEC941470CB86F2F2367EB14F7EB - -Count = 211 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B -CT = FEC941470CB835CDAA5771759BAD - -Count = 212 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C -CT = FEC941470CB8CAD9A8AA6B27AE79 - -Count = 213 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB88DAD6DAA1D84FF3E - -Count = 214 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB83CF79C822608066A - -Count = 215 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB8FC25C60EBCBDBF97 - -Count = 216 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB8ABF90571E73452A0 - -Count = 217 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB86951F061EEA8893C - -Count = 218 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB89813DD6075E3756E - -Count = 219 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB84BDE63F020E5E93D - -Count = 220 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB8EB77F333185DB974 - -Count = 221 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB85BDD44147176643C - -Count = 222 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB87132606EF8C266FF - -Count = 223 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB8AC58C574540818DA - -Count = 224 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB8513E625C7B56A4F3 - -Count = 225 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB888603A44B19BA70C - -Count = 226 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB838ED57CD528BFD6B - -Count = 227 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB88A7518D482232C4F - -Count = 228 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB8533C7B9B87167B92 - -Count = 229 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB8954B31BDF1EE0797 - -Count = 230 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB8601C761CD9C5D0C8 - -Count = 231 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB8A73D6CEDFBB7932B - -Count = 232 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = -CT = FEC941470CB85931CD20ED8103BD44 - -Count = 233 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00 -CT = FEC941470CB8599EC80951FCA3BFE9 - -Count = 234 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001 -CT = FEC941470CB859B1D1CA5FBCEF4468 - -Count = 235 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102 -CT = FEC941470CB859BEB613FF8BBA93B3 - -Count = 236 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203 -CT = FEC941470CB85913F95E696DD4D5F1 - -Count = 237 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304 -CT = FEC941470CB859DD5CE1F139A360A3 - -Count = 238 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405 -CT = FEC941470CB85994D01E25C108040A - -Count = 239 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506 -CT = FEC941470CB85935D119029A091215 - -Count = 240 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304050607 -CT = FEC941470CB859B944D0EA31D6909F - -Count = 241 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708 -CT = FEC941470CB859719A49EBBDFAEC37 - -Count = 242 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506070809 -CT = FEC941470CB859FA999B587FE97CC4 - -Count = 243 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A -CT = FEC941470CB859BCA00664921E76A7 - -Count = 244 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B -CT = FEC941470CB859E6428F54087F1AE1 - -Count = 245 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C -CT = FEC941470CB85919568DA9122D2F35 - -Count = 246 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB8595E2248A9648E7E72 - -Count = 247 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859EF78B9815F028726 - -Count = 248 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB8592FAAE30DC5B73EDB - -Count = 249 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859787620729E3ED3EC - -Count = 250 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859BADED56297A20870 - -Count = 251 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB8594B9CF8630CE9F422 - -Count = 252 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859985146F359EF6871 - -Count = 253 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB85938F8D63061573838 - -Count = 254 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB85988526117087CE570 - -Count = 255 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859A2BD456D81C8E7B3 - -Count = 256 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB8597FD7E0772D029996 - -Count = 257 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB85982B1475F025C25BF - -Count = 258 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB8595BEF1F47C8912640 - -Count = 259 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859EB6272CE2B817C27 - -Count = 260 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB85959FA3DD7FB29AD03 - -Count = 261 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB85980B35E98FE1CFADE - -Count = 262 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB85946C414BE88E486DB - -Count = 263 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859B393531FA0CF5184 - -Count = 264 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB85974B249EE82BD1267 - -Count = 265 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = -CT = FEC941470CB859D7A1F29672CF3310E0 - -Count = 266 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00 -CT = FEC941470CB859D70EF7BFCEB293124D - -Count = 267 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001 -CT = FEC941470CB859D721EE7CC0F2DFE9CC - -Count = 268 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102 -CT = FEC941470CB859D72E89A560C58A3E17 - -Count = 269 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203 -CT = FEC941470CB859D783C6E8F623E47855 - -Count = 270 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304 -CT = FEC941470CB859D74D63576E7793CD07 - -Count = 271 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405 -CT = FEC941470CB859D704EFA8BA8F38A9AE - -Count = 272 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506 -CT = FEC941470CB859D7A5EEAF9DD439BFB1 - -Count = 273 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304050607 -CT = FEC941470CB859D7297B66757FE63D3B - -Count = 274 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708 -CT = FEC941470CB859D7E1A5FF74F3CA4193 - -Count = 275 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506070809 -CT = FEC941470CB859D76AA62DC731D9D160 - -Count = 276 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A -CT = FEC941470CB859D72C9FB0FBDC2EDB03 - -Count = 277 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B -CT = FEC941470CB859D7767D39CB464FB745 - -Count = 278 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D789693B365C1D8291 - -Count = 279 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D7CE1DFE362ABED3D6 - -Count = 280 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D77F470F1E11322A82 - -Count = 281 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D7BF9555928B87937F - -Count = 282 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D7E84996EDD00E7E48 - -Count = 283 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D72AE163FDD992A5D4 - -Count = 284 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D7DBA34EFC42D95986 - -Count = 285 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D7086EF06C17DFC5D5 - -Count = 286 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D7A8C760AF2F67959C - -Count = 287 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D7186DD788464C48D4 - -Count = 288 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D73282F3F2CFF84A17 - -Count = 289 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D7EFE856E863323432 - -Count = 290 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D7128EF1C04C6C881B - -Count = 291 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D7CBD0A9D886A18BE4 - -Count = 292 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D77B5DC45165B1D183 - -Count = 293 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D7C9C58B48B51900A7 - -Count = 294 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D7108CE807B02C577A - -Count = 295 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D7D6FBA221C6D42B7F - -Count = 296 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D723ACE580EEFFFC20 - -Count = 297 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D7E48DFF71CC8DBFC3 - -Count = 298 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = -CT = FEC941470CB859D7354BDE6B3DDA94AA48 - -Count = 299 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00 -CT = FEC941470CB859D735E4DB4281A734A8E5 - -Count = 300 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001 -CT = FEC941470CB859D735CBC2818FE7785364 - -Count = 301 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102 -CT = FEC941470CB859D735C4A5582FD02D84BF - -Count = 302 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203 -CT = FEC941470CB859D73569EA15B93643C2FD - -Count = 303 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304 -CT = FEC941470CB859D735A74FAA21623477AF - -Count = 304 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405 -CT = FEC941470CB859D735EEC355F59A9F1306 - -Count = 305 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506 -CT = FEC941470CB859D7354FC252D2C19E0519 - -Count = 306 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304050607 -CT = FEC941470CB859D735C3579B3A6A418793 - -Count = 307 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708 -CT = FEC941470CB859D7350B89023BE66DFB3B - -Count = 308 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506070809 -CT = FEC941470CB859D735808AD088247E6BC8 - -Count = 309 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A -CT = FEC941470CB859D735C6B34DB4C98961AB - -Count = 310 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B -CT = FEC941470CB859D7359C51C48453E80DED - -Count = 311 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D7356345C67949BA3839 - -Count = 312 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735243103793F19697E - -Count = 313 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735956BF2510495902A - -Count = 314 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D73555B9A8DD9E2029D7 - -Count = 315 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D73502656BA2C5A9C4E0 - -Count = 316 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735C0CD9EB2CC351F7C - -Count = 317 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735318FB3B3577EE32E - -Count = 318 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735E2420D2302787F7D - -Count = 319 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D73542EB9DE03AC02F34 - -Count = 320 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735F2412AC753EBF27C - -Count = 321 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735D8AE0EBDDA5FF0BF - -Count = 322 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D73505C4ABA776958E9A - -Count = 323 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735F8A20C8F59CB32B3 - -Count = 324 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D73521FC54979306314C - -Count = 325 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D7359171391E70166B2B - -Count = 326 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D73523E97607A0BEBA0F - -Count = 327 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735FAA01548A58BEDD2 - -Count = 328 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D7353CD75F6ED37391D7 - -Count = 329 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735C98018CFFB584688 - -Count = 330 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D7350EA1023ED92A056B - -Count = 331 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = -CT = FEC941470CB859D735256D1107BAA5D56B3C - -Count = 332 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00 -CT = FEC941470CB859D73525C2142E06D8756991 - -Count = 333 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001 -CT = FEC941470CB859D73525ED0DED0898399210 - -Count = 334 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102 -CT = FEC941470CB859D73525E26A34A8AF6C45CB - -Count = 335 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203 -CT = FEC941470CB859D735254F25793E49020389 - -Count = 336 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304 -CT = FEC941470CB859D735258180C6A61D75B6DB - -Count = 337 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405 -CT = FEC941470CB859D73525C80C3972E5DED272 - -Count = 338 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506 -CT = FEC941470CB859D73525690D3E55BEDFC46D - -Count = 339 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304050607 -CT = FEC941470CB859D73525E598F7BD150046E7 - -Count = 340 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708 -CT = FEC941470CB859D735252D466EBC992C3A4F - -Count = 341 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506070809 -CT = FEC941470CB859D73525A645BC0F5B3FAABC - -Count = 342 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A -CT = FEC941470CB859D73525E07C2133B6C8A0DF - -Count = 343 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B -CT = FEC941470CB859D73525BA9EA8032CA9CC99 - -Count = 344 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D73525458AAAFE36FBF94D - -Count = 345 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D7352502FE6FFE4058A80A - -Count = 346 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D73525B3A49ED67BD4515E - -Count = 347 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735257376C45AE161E8A3 - -Count = 348 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D7352524AA0725BAE80594 - -Count = 349 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D73525E602F235B374DE08 - -Count = 350 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735251740DF34283F225A - -Count = 351 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D73525C48D61A47D39BE09 - -Count = 352 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735256424F1674581EE40 - -Count = 353 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D73525D48E46402CAA3308 - -Count = 354 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D73525FE61623AA51E31CB - -Count = 355 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D73525230BC72009D44FEE - -Count = 356 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D73525DE6D6008268AF3C7 - -Count = 357 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D7352507333810EC47F038 - -Count = 358 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D73525B7BE55990F57AA5F - -Count = 359 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D7352505261A80DFFF7B7B - -Count = 360 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D73525DC6F79CFDACA2CA6 - -Count = 361 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735251A1833E9AC3250A3 - -Count = 362 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D73525EF4F7448841987FC - -Count = 363 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D73525286E6EB9A66BC41F - -Count = 364 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = -CT = FEC941470CB859D735255BFCFBA78DDD0631FE - -Count = 365 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00 -CT = FEC941470CB859D735255B53FE8E31A0A63353 - -Count = 366 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001 -CT = FEC941470CB859D735255B7CE74D3FE0EAC8D2 - -Count = 367 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102 -CT = FEC941470CB859D735255B7380949FD7BF1F09 - -Count = 368 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203 -CT = FEC941470CB859D735255BDECFD90931D1594B - -Count = 369 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304 -CT = FEC941470CB859D735255B106A669165A6EC19 - -Count = 370 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405 -CT = FEC941470CB859D735255B59E699459D0D88B0 - -Count = 371 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506 -CT = FEC941470CB859D735255BF8E79E62C60C9EAF - -Count = 372 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304050607 -CT = FEC941470CB859D735255B7472578A6DD31C25 - -Count = 373 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708 -CT = FEC941470CB859D735255BBCACCE8BE1FF608D - -Count = 374 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506070809 -CT = FEC941470CB859D735255B37AF1C3823ECF07E - -Count = 375 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A -CT = FEC941470CB859D735255B71968104CE1BFA1D - -Count = 376 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B2B740834547A965B - -Count = 377 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255BD4600AC94E28A38F - -Count = 378 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B9314CFC9388BF2C8 - -Count = 379 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B224E3EE103070B9C - -Count = 380 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255BE29C646D99B2B261 - -Count = 381 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255BB540A712C23B5F56 - -Count = 382 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B77E85202CBA784CA - -Count = 383 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B86AA7F0350EC7898 - -Count = 384 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B5567C19305EAE4CB - -Count = 385 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255BF5CE51503D52B482 - -Count = 386 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B4564E677547969CA - -Count = 387 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B6F8BC20DDDCD6B09 - -Count = 388 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255BB2E167177107152C - -Count = 389 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B4F87C03F5E59A905 - -Count = 390 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B96D998279494AAFA - -Count = 391 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B2654F5AE7784F09D - -Count = 392 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B94CCBAB7A72C21B9 - -Count = 393 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B4D85D9F8A2197664 - -Count = 394 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B8BF293DED4E10A61 - -Count = 395 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B7EA5D47FFCCADD3E - -Count = 396 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255BB984CE8EDEB89EDD - -Count = 397 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = -CT = FEC941470CB859D735255B80B658144E4BAC29D0 - -Count = 398 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00 -CT = FEC941470CB859D735255B80195D3DF2360C2B7D - -Count = 399 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001 -CT = FEC941470CB859D735255B803644FEFC7640D0FC - -Count = 400 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102 -CT = FEC941470CB859D735255B803923275C41150727 - -Count = 401 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203 -CT = FEC941470CB859D735255B80946C6ACAA77B4165 - -Count = 402 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304 -CT = FEC941470CB859D735255B805AC9D552F30CF437 - -Count = 403 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405 -CT = FEC941470CB859D735255B8013452A860BA7909E - -Count = 404 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506 -CT = FEC941470CB859D735255B80B2442DA150A68681 - -Count = 405 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304050607 -CT = FEC941470CB859D735255B803ED1E449FB79040B - -Count = 406 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708 -CT = FEC941470CB859D735255B80F60F7D48775578A3 - -Count = 407 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506070809 -CT = FEC941470CB859D735255B807D0CAFFBB546E850 - -Count = 408 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A -CT = FEC941470CB859D735255B803B3532C758B1E233 - -Count = 409 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B8061D7BBF7C2D08E75 - -Count = 410 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B809EC3B90AD882BBA1 - -Count = 411 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80D9B77C0AAE21EAE6 - -Count = 412 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B8068ED8D2295AD13B2 - -Count = 413 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80A83FD7AE0F18AA4F - -Count = 414 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80FFE314D154914778 - -Count = 415 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B803D4BE1C15D0D9CE4 - -Count = 416 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80CC09CCC0C64660B6 - -Count = 417 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B801FC472509340FCE5 - -Count = 418 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80BF6DE293ABF8ACAC - -Count = 419 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B800FC755B4C2D371E4 - -Count = 420 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80252871CE4B677327 - -Count = 421 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80F842D4D4E7AD0D02 - -Count = 422 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80052473FCC8F3B12B - -Count = 423 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80DC7A2BE4023EB2D4 - -Count = 424 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B806CF7466DE12EE8B3 - -Count = 425 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80DE6F097431863997 - -Count = 426 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B8007266A3B34B36E4A - -Count = 427 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80C151201D424B124F - -Count = 428 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80340667BC6A60C510 - -Count = 429 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80F3277D4D481286F3 - -Count = 430 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = -CT = FEC941470CB859D735255B80669A87B729D1F56CAC - -Count = 431 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00 -CT = FEC941470CB859D735255B806635829E95AC556E01 - -Count = 432 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001 -CT = FEC941470CB859D735255B80661A9B5D9BEC199580 - -Count = 433 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102 -CT = FEC941470CB859D735255B806615FC843BDB4C425B - -Count = 434 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203 -CT = FEC941470CB859D735255B8066B8B3C9AD3D220419 - -Count = 435 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304 -CT = FEC941470CB859D735255B8066761676356955B14B - -Count = 436 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405 -CT = FEC941470CB859D735255B80663F9A89E191FED5E2 - -Count = 437 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506 -CT = FEC941470CB859D735255B80669E9B8EC6CAFFC3FD - -Count = 438 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304050607 -CT = FEC941470CB859D735255B8066120E472E61204177 - -Count = 439 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708 -CT = FEC941470CB859D735255B8066DAD0DE2FED0C3DDF - -Count = 440 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506070809 -CT = FEC941470CB859D735255B806651D30C9C2F1FAD2C - -Count = 441 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A -CT = FEC941470CB859D735255B806617EA91A0C2E8A74F - -Count = 442 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80664D0818905889CB09 - -Count = 443 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B8066B21C1A6D42DBFEDD - -Count = 444 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B8066F568DF6D3478AF9A - -Count = 445 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B806644322E450FF456CE - -Count = 446 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B806684E074C99541EF33 - -Count = 447 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B8066D33CB7B6CEC80204 - -Count = 448 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B8066119442A6C754D998 - -Count = 449 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B8066E0D66FA75C1F25CA - -Count = 450 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B8066331BD1370919B999 - -Count = 451 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B806693B241F431A1E9D0 - -Count = 452 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80662318F6D3588A3498 - -Count = 453 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B806609F7D2A9D13E365B - -Count = 454 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B8066D49D77B37DF4487E - -Count = 455 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B806629FBD09B52AAF457 - -Count = 456 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B8066F0A588839867F7A8 - -Count = 457 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80664028E50A7B77ADCF - -Count = 458 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B8066F2B0AA13ABDF7CEB - -Count = 459 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80662BF9C95CAEEA2B36 - -Count = 460 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B8066ED8E837AD8125733 - -Count = 461 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B806618D9C4DBF039806C - -Count = 462 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B8066DFF8DE2AD24BC38F - -Count = 463 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = -CT = FEC941470CB859D735255B80663E379995F290E84795 - -Count = 464 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00 -CT = FEC941470CB859D735255B80663E989CBC4EED484538 - -Count = 465 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001 -CT = FEC941470CB859D735255B80663EB7857F40AD04BEB9 - -Count = 466 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102 -CT = FEC941470CB859D735255B80663EB8E2A6E09A516962 - -Count = 467 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203 -CT = FEC941470CB859D735255B80663E15ADEB767C3F2F20 - -Count = 468 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304 -CT = FEC941470CB859D735255B80663EDB0854EE28489A72 - -Count = 469 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405 -CT = FEC941470CB859D735255B80663E9284AB3AD0E3FEDB - -Count = 470 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E3385AC1D8BE2E8C4 - -Count = 471 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663EBF1065F5203D6A4E - -Count = 472 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E77CEFCF4AC1116E6 - -Count = 473 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663EFCCD2E476E028615 - -Count = 474 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663EBAF4B37B83F58C76 - -Count = 475 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663EE0163A4B1994E030 - -Count = 476 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E1F0238B603C6D5E4 - -Count = 477 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E5876FDB6756584A3 - -Count = 478 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663EE92C0C9E4EE97DF7 - -Count = 479 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E29FE5612D45CC40A - -Count = 480 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E7E22956D8FD5293D - -Count = 481 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663EBC8A607D8649F2A1 - -Count = 482 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E4DC84D7C1D020EF3 - -Count = 483 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E9E05F3EC480492A0 - -Count = 484 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E3EAC632F70BCC2E9 - -Count = 485 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E8E06D40819971FA1 - -Count = 486 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663EA4E9F07290231D62 - -Count = 487 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E798355683CE96347 - -Count = 488 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E84E5F24013B7DF6E - -Count = 489 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E5DBBAA58D97ADC91 - -Count = 490 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663EED36C7D13A6A86F6 - -Count = 491 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E5FAE88C8EAC257D2 - -Count = 492 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E86E7EB87EFF7000F - -Count = 493 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E4090A1A1990F7C0A - -Count = 494 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663EB5C7E600B124AB55 - -Count = 495 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E72E6FCF19356E8B6 - -Count = 496 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = -CT = FEC941470CB859D735255B80663E80CA51659B586156DC - -Count = 497 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00 -CT = FEC941470CB859D735255B80663E8065544C2725C15471 - -Count = 498 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001 -CT = FEC941470CB859D735255B80663E804A4D8F29658DAFF0 - -Count = 499 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102 -CT = FEC941470CB859D735255B80663E80452A568952D8782B - -Count = 500 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203 -CT = FEC941470CB859D735255B80663E80E8651B1FB4B63E69 - -Count = 501 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304 -CT = FEC941470CB859D735255B80663E8026C0A487E0C18B3B - -Count = 502 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405 -CT = FEC941470CB859D735255B80663E806F4C5B53186AEF92 - -Count = 503 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E80CE4D5C74436BF98D - -Count = 504 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E8042D8959CE8B47B07 - -Count = 505 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E808A060C9D649807AF - -Count = 506 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E800105DE2EA68B975C - -Count = 507 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E80473C43124B7C9D3F - -Count = 508 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E801DDECA22D11DF179 - -Count = 509 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E80E2CAC8DFCB4FC4AD - -Count = 510 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E80A5BE0DDFBDEC95EA - -Count = 511 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E8014E4FCF786606CBE - -Count = 512 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E80D436A67B1CD5D543 - -Count = 513 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E8083EA6504475C3874 - -Count = 514 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E80414290144EC0E3E8 - -Count = 515 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E80B000BD15D58B1FBA - -Count = 516 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E8063CD0385808D83E9 - -Count = 517 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E80C3649346B835D3A0 - -Count = 518 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E8073CE2461D11E0EE8 - -Count = 519 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E805921001B58AA0C2B - -Count = 520 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E80844BA501F460720E - -Count = 521 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E80792D0229DB3ECE27 - -Count = 522 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E80A0735A3111F3CDD8 - -Count = 523 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E8010FE37B8F2E397BF - -Count = 524 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E80A26678A1224B469B - -Count = 525 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807B2F1BEE277E1146 - -Count = 526 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E80BD5851C851866D43 - -Count = 527 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E80480F166979ADBA1C - -Count = 528 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E808F2E0C985BDFF9FF - -Count = 529 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = -CT = FEC941470CB859D735255B80663E807AB39D122E7B101B1A - -Count = 530 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00 -CT = FEC941470CB859D735255B80663E807A1C983B9206B019B7 - -Count = 531 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001 -CT = FEC941470CB859D735255B80663E807A3381F89C46FCE236 - -Count = 532 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102 -CT = FEC941470CB859D735255B80663E807A3CE6213C71A935ED - -Count = 533 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A91A96CAA97C773AF - -Count = 534 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A5F0CD332C3B0C6FD - -Count = 535 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A16802CE63B1BA254 - -Count = 536 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807AB7812BC1601AB44B - -Count = 537 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A3B14E229CBC536C1 - -Count = 538 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807AF3CA7B2847E94A69 - -Count = 539 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A78C9A99B85FADA9A - -Count = 540 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A3EF034A7680DD0F9 - -Count = 541 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A6412BD97F26CBCBF - -Count = 542 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A9B06BF6AE83E896B - -Count = 543 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807ADC727A6A9E9DD82C - -Count = 544 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A6D288B42A5112178 - -Count = 545 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807AADFAD1CE3FA49885 - -Count = 546 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807AFA2612B1642D75B2 - -Count = 547 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A388EE7A16DB1AE2E - -Count = 548 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807AC9CCCAA0F6FA527C - -Count = 549 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A1A017430A3FCCE2F - -Count = 550 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807ABAA8E4F39B449E66 - -Count = 551 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A0A0253D4F26F432E - -Count = 552 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A20ED77AE7BDB41ED - -Count = 553 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807AFD87D2B4D7113FC8 - -Count = 554 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A00E1759CF84F83E1 - -Count = 555 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807AD9BF2D843282801E - -Count = 556 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A6932400DD192DA79 - -Count = 557 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807ADBAA0F14013A0B5D - -Count = 558 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A02E36C5B040F5C80 - -Count = 559 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807AC494267D72F72085 - -Count = 560 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A31C361DC5ADCF7DA - -Count = 561 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807AF6E27B2D78AEB439 - -Count = 562 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = -CT = FEC941470CB859D735255B80663E807A63A849D541118342CC - -Count = 563 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63074CFCFD6C234061 - -Count = 564 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A6328553FF32C6FBBE0 - -Count = 565 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A632732E6531B3A6C3B - -Count = 566 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A638A7DABC5FD542A79 - -Count = 567 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A6344D8145DA9239F2B - -Count = 568 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A630D54EB895188FB82 - -Count = 569 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63AC55ECAE0A89ED9D - -Count = 570 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A6320C02546A1566F17 - -Count = 571 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63E81EBC472D7A13BF - -Count = 572 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63631D6EF4EF69834C - -Count = 573 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A632524F3C8029E892F - -Count = 574 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A637FC67AF898FFE569 - -Count = 575 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A6380D2780582ADD0BD - -Count = 576 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63C7A6BD05F40E81FA - -Count = 577 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A6376FC4C2DCF8278AE - -Count = 578 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63B62E16A15537C153 - -Count = 579 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63E1F2D5DE0EBE2C64 - -Count = 580 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63235A20CE0722F7F8 - -Count = 581 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D2180DCF9C690BAA - -Count = 582 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A6301D5B35FC96F97F9 - -Count = 583 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63A17C239CF1D7C7B0 - -Count = 584 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A6311D694BB98FC1AF8 - -Count = 585 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A633B39B0C11148183B - -Count = 586 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63E65315DBBD82661E - -Count = 587 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A631B35B2F392DCDA37 - -Count = 588 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63C26BEAEB5811D9C8 - -Count = 589 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A6372E68762BB0183AF - -Count = 590 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63C07EC87B6BA9528B - -Count = 591 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A631937AB346E9C0556 - -Count = 592 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63DF40E11218647953 - -Count = 593 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A632A17A6B3304FAE0C - -Count = 594 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63ED36BC42123DEDEF - -Count = 595 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = -CT = FEC941470CB859D735255B80663E807A63D56D03C2D7ECE3838B - -Count = 596 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D5C206EB6B91438126 - -Count = 597 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D5ED1F2865D10F7AA7 - -Count = 598 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D5E278F1C5E65AAD7C - -Count = 599 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D54F37BC530034EB3E - -Count = 600 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D5819203CB54435E6C - -Count = 601 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D5C81EFC1FACE83AC5 - -Count = 602 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D5691FFB38F7E92CDA - -Count = 603 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D5E58A32D05C36AE50 - -Count = 604 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52D54ABD1D01AD2F8 - -Count = 605 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D5A65779621209420B - -Count = 606 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D5E06EE45EFFFE4868 - -Count = 607 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D5BA8C6D6E659F242E - -Count = 608 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D545986F937FCD11FA - -Count = 609 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D502ECAA93096E40BD - -Count = 610 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D5B3B65BBB32E2B9E9 - -Count = 611 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D573640137A8570014 - -Count = 612 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D524B8C248F3DEED23 - -Count = 613 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D5E6103758FA4236BF - -Count = 614 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D517521A596109CAED - -Count = 615 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D5C49FA4C9340F56BE - -Count = 616 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D56436340A0CB706F7 - -Count = 617 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D5D49C832D659CDBBF - -Count = 618 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D5FE73A757EC28D97C - -Count = 619 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52319024D40E2A759 - -Count = 620 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D5DE7FA5656FBC1B70 - -Count = 621 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D50721FD7DA571188F - -Count = 622 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D5B7AC90F4466142E8 - -Count = 623 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D50534DFED96C993CC - -Count = 624 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D5DC7DBCA293FCC411 - -Count = 625 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D51A0AF684E504B814 - -Count = 626 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D5EF5DB125CD2F6F4B - -Count = 627 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D5287CABD4EF5D2CA8 - -Count = 628 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = -CT = FEC941470CB859D735255B80663E807A63D52AF436ED08F7854A6A - -Count = 629 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A5B33C4B48A2548C7 - -Count = 630 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A742A07BACA69B346 - -Count = 631 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A7B4DDE1AFD3C649D - -Count = 632 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52AD602938C1B5222DF - -Count = 633 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A18A72C144F25978D - -Count = 634 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A512BD3C0B78EF324 - -Count = 635 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52AF02AD4E7EC8FE53B - -Count = 636 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A7CBF1D0F475067B1 - -Count = 637 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52AB461840ECB7C1B19 - -Count = 638 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A3F6256BD096F8BEA - -Count = 639 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A795BCB81E4988189 - -Count = 640 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A23B942B17EF9EDCF - -Count = 641 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52ADCAD404C64ABD81B - -Count = 642 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A9BD9854C1208895C - -Count = 643 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A2A83746429847008 - -Count = 644 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52AEA512EE8B331C9F5 - -Count = 645 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52ABD8DED97E8B824C2 - -Count = 646 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A7F251887E124FF5E - -Count = 647 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A8E6735867A6F030C - -Count = 648 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A5DAA8B162F699F5F - -Count = 649 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52AFD031BD517D1CF16 - -Count = 650 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A4DA9ACF27EFA125E - -Count = 651 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A67468888F74E109D - -Count = 652 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52ABA2C2D925B846EB8 - -Count = 653 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A474A8ABA74DAD291 - -Count = 654 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A9E14D2A2BE17D16E - -Count = 655 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A2E99BF2B5D078B09 - -Count = 656 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A9C01F0328DAF5A2D - -Count = 657 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A4548937D889A0DF0 - -Count = 658 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A833FD95BFE6271F5 - -Count = 659 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A76689EFAD649A6AA - -Count = 660 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52AB149840BF43BE549 - -Count = 661 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71528442BF6E4962EA - -Count = 662 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71FD816B0313E96047 - -Count = 663 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71D298A80D53A59BC6 - -Count = 664 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71DDFF71AD64F04C1D - -Count = 665 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A7170B03C3B829E0A5F - -Count = 666 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71BE1583A3D6E9BF0D - -Count = 667 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71F7997C772E42DBA4 - -Count = 668 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A7156987B507543CDBB - -Count = 669 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71DA0DB2B8DE9C4F31 - -Count = 670 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A7112D32BB952B03399 - -Count = 671 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A7199D0F90A90A3A36A - -Count = 672 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71DFE964367D54A909 - -Count = 673 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71850BED06E735C54F - -Count = 674 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A717A1FEFFBFD67F09B - -Count = 675 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A713D6B2AFB8BC4A1DC - -Count = 676 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A718C31DBD3B0485888 - -Count = 677 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A714CE3815F2AFDE175 - -Count = 678 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A711B3F422071740C42 - -Count = 679 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71D997B73078E8D7DE - -Count = 680 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A7128D59A31E3A32B8C - -Count = 681 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71FB1824A1B6A5B7DF - -Count = 682 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A715BB1B4628E1DE796 - -Count = 683 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71EB1B0345E7363ADE - -Count = 684 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71C1F4273F6E82381D - -Count = 685 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A711C9E8225C2484638 - -Count = 686 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71E1F8250DED16FA11 - -Count = 687 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A7138A67D1527DBF9EE - -Count = 688 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71882B109CC4CBA389 - -Count = 689 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A713AB35F85146372AD - -Count = 690 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71E3FA3CCA11562570 - -Count = 691 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71258D76EC67AE5975 - -Count = 692 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71D0DA314D4F858E2A - -Count = 693 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A7117FB2BBC6DF7CDC9 - -Count = 694 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A7182F7CF78EF4708A1F1 - -Count = 695 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A718258CA51533AA8A35C - -Count = 696 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A718277D3925D7AE458DD - -Count = 697 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A718278B44BFD4DB18F06 - -Count = 698 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A7182D5FB066BABDFC944 - -Count = 699 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71821B5EB9F3FFA87C16 - -Count = 700 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A718252D24627070318BF - -Count = 701 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A7182F3D341005C020EA0 - -Count = 702 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71827F4688E8F7DD8C2A - -Count = 703 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A7182B79811E97BF1F082 - -Count = 704 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71823C9BC35AB9E26071 - -Count = 705 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71827AA25E6654156A12 - -Count = 706 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71822040D756CE740654 - -Count = 707 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A7182DF54D5ABD4263380 - -Count = 708 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A7182982010ABA28562C7 - -Count = 709 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A7182297AE18399099B93 - -Count = 710 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A7182E9A8BB0F03BC226E - -Count = 711 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A7182BE7478705835CF59 - -Count = 712 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71827CDC8D6051A914C5 - -Count = 713 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71828D9EA061CAE2E897 - -Count = 714 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71825E531EF19FE474C4 - -Count = 715 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A7182FEFA8E32A75C248D - -Count = 716 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71824E503915CE77F9C5 - -Count = 717 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A718264BF1D6F47C3FB06 - -Count = 718 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A7182B9D5B875EB098523 - -Count = 719 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A718244B31F5DC457390A - -Count = 720 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829DED47450E9A3AF5 - -Count = 721 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71822D602ACCED8A6092 - -Count = 722 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829FF865D53D22B1B6 - -Count = 723 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A718246B1069A3817E66B - -Count = 724 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A718280C64CBC4EEF9A6E - -Count = 725 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A718275910B1D66C44D31 - -Count = 726 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A7182B2B011EC44B60ED2 - -Count = 727 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F40136AEEE40417C1 - -Count = 728 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829FEF16435299A4156C - -Count = 729 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829FC00F805CD9E8EEED - -Count = 730 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829FCF6859FCEEBD3936 - -Count = 731 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F6227146A08D37F74 - -Count = 732 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829FAC82ABF25CA4CA26 - -Count = 733 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829FE50E5426A40FAE8F - -Count = 734 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F440F5301FF0EB890 - -Count = 735 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829FC89A9AE954D13A1A - -Count = 736 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F004403E8D8FD46B2 - -Count = 737 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F8B47D15B1AEED641 - -Count = 738 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829FCD7E4C67F719DC22 - -Count = 739 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F979CC5576D78B064 - -Count = 740 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F6888C7AA772A85B0 - -Count = 741 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F2FFC02AA0189D4F7 - -Count = 742 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F9EA6F3823A052DA3 - -Count = 743 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F5E74A90EA0B0945E - -Count = 744 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F09A86A71FB397969 - -Count = 745 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829FCB009F61F2A5A2F5 - -Count = 746 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F3A42B26069EE5EA7 - -Count = 747 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829FE98F0CF03CE8C2F4 - -Count = 748 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F49269C33045092BD - -Count = 749 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829FF98C2B146D7B4FF5 - -Count = 750 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829FD3630F6EE4CF4D36 - -Count = 751 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0E09AA7448053313 - -Count = 752 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829FF36F0D5C675B8F3A - -Count = 753 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F2A315544AD968CC5 - -Count = 754 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F9ABC38CD4E86D6A2 - -Count = 755 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F282477D49E2E0786 - -Count = 756 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829FF16D149B9B1B505B - -Count = 757 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F371A5EBDEDE32C5E - -Count = 758 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829FC24D191CC5C8FB01 - -Count = 759 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F056C03EDE7BAB8E2 - -Count = 760 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BE9115FD98DC24AD6 - -Count = 761 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B46147665F062487B - -Count = 762 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B690DB56BB02EB3FA - -Count = 763 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B666A6CCB877B6421 - -Count = 764 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BCB25215D61152263 - -Count = 765 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B05809EC535629731 - -Count = 766 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B4C0C6111CDC9F398 - -Count = 767 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BED0D663696C8E587 - -Count = 768 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6198AFDE3D17670D - -Count = 769 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA94636DFB13B1BA5 - -Count = 770 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B2245E46C73288B56 - -Count = 771 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B647C79509EDF8135 - -Count = 772 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B3E9EF06004BEED73 - -Count = 773 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BC18AF29D1EECD8A7 - -Count = 774 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B86FE379D684F89E0 - -Count = 775 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B37A4C6B553C370B4 - -Count = 776 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF7769C39C976C949 - -Count = 777 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA0AA5F4692FF247E - -Count = 778 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6202AA569B63FFE2 - -Count = 779 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B93408757002803B0 - -Count = 780 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B408D39C7552E9FE3 - -Count = 781 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BE024A9046D96CFAA - -Count = 782 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B508E1E2304BD12E2 - -Count = 783 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B7A613A598D091021 - -Count = 784 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA70B9F4321C36E04 - -Count = 785 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B5A6D386B0E9DD22D - -Count = 786 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B83336073C450D1D2 - -Count = 787 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B33BE0DFA27408BB5 - -Count = 788 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B812642E3F7E85A91 - -Count = 789 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B586F21ACF2DD0D4C - -Count = 790 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B9E186B8A84257149 - -Count = 791 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6B4F2C2BAC0EA616 - -Count = 792 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BAC6E36DA8E7CE5F5 - -Count = 793 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF321133DC6BF15EAF6 - -Count = 794 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF38E16147AC2B5E85B - -Count = 795 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A10FD77482F913DA - -Count = 796 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AE680ED4B5ACC401 - -Count = 797 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF30327434253C28243 - -Count = 798 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3CD82FCDA07B53711 - -Count = 799 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3840E030EFF1E53B8 - -Count = 800 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3250F0429A41F45A7 - -Count = 801 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A99ACDC10FC0C72D - -Count = 802 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3614454C083ECBB85 - -Count = 803 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3EA47867341FF2B76 - -Count = 804 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AC7E1B4FAC082115 - -Count = 805 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3F69C927F36694D53 - -Count = 806 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3098890822C3B7887 - -Count = 807 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF34EFC55825A9829C0 - -Count = 808 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3FFA6A4AA6114D094 - -Count = 809 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF33F74FE26FBA16969 - -Count = 810 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF368A83D59A028845E - -Count = 811 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AA00C849A9B45FC2 - -Count = 812 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF35B42E54832FFA390 - -Count = 813 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3888F5BD867F93FC3 - -Count = 814 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF32826CB1B5F416F8A - -Count = 815 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3988C7C3C366AB2C2 - -Count = 816 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3B2635846BFDEB001 - -Count = 817 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF36F09FD5C1314CE24 - -Count = 818 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3926F5A743C4A720D - -Count = 819 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF34B31026CF68771F2 - -Count = 820 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3FBBC6FE515972B95 - -Count = 821 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3492420FCC53FFAB1 - -Count = 822 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3906D43B3C00AAD6C - -Count = 823 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3561A0995B6F2D169 - -Count = 824 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A34D4E349ED90636 - -Count = 825 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3646C54C5BCAB45D5 - -Count = 826 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C5B28C82D80F3CB89 - -Count = 827 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CF42DE191FD53C924 - -Count = 828 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CDB34229FBD1F32A5 - -Count = 829 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD453FB3F8A4AE57E - -Count = 830 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C791CB6A96C24A33C - -Count = 831 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CB7B909313853166E - -Count = 832 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CFE35F6E5C0F872C7 - -Count = 833 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C5F34F1C29BF964D8 - -Count = 834 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD3A1382A3026E652 - -Count = 835 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1B7FA12BBC0A9AFA - -Count = 836 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C907C73987E190A09 - -Count = 837 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD645EEA493EE006A - -Count = 838 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C8CA76794098F6C2C - -Count = 839 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C73B3656913DD59F8 - -Count = 840 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C34C7A069657E08BF - -Count = 841 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C859D51415EF2F1EB - -Count = 842 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C454F0BCDC4474816 - -Count = 843 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1293C8B29FCEA521 - -Count = 844 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD03B3DA296527EBD - -Count = 845 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C217910A30D1982EF - -Count = 846 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CF2B4AE33581F1EBC - -Count = 847 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C521D3EF060A74EF5 - -Count = 848 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CE2B789D7098C93BD - -Count = 849 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CC858ADAD8038917E - -Count = 850 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C153208B72CF2EF5B - -Count = 851 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CE854AF9F03AC5372 - -Count = 852 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C310AF787C961508D - -Count = 853 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C81879A0E2A710AEA - -Count = 854 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C331FD517FAD9DBCE - -Count = 855 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CEA56B658FFEC8C13 - -Count = 856 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2C21FC7E8914F016 - -Count = 857 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD976BBDFA13F2749 - -Count = 858 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1E57A12E834D64AA - -Count = 859 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27B83F449CB1372B2C - -Count = 860 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27173A6D20CC972981 - -Count = 861 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273823AE2E8CDBD200 - -Count = 862 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273744778EBB8E05DB - -Count = 863 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C279A0B3A185DE04399 - -Count = 864 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2754AE85800997F6CB - -Count = 865 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C271D227A54F13C9262 - -Count = 866 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27BC237D73AA3D847D - -Count = 867 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2730B6B49B01E206F7 - -Count = 868 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F8682D9A8DCE7A5F - -Count = 869 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27736BFF294FDDEAAC - -Count = 870 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2735526215A22AE0CF - -Count = 871 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C276FB0EB25384B8C89 - -Count = 872 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2790A4E9D82219B95D - -Count = 873 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D7D02CD854BAE81A - -Count = 874 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27668ADDF06F36114E - -Count = 875 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27A658877CF583A8B3 - -Count = 876 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F1844403AE0A4584 - -Count = 877 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27332CB113A7969E18 - -Count = 878 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27C26E9C123CDD624A - -Count = 879 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2711A3228269DBFE19 - -Count = 880 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27B10AB2415163AE50 - -Count = 881 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2701A0056638487318 - -Count = 882 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C272B4F211CB1FC71DB - -Count = 883 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F62584061D360FFE - -Count = 884 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C270B43232E3268B3D7 - -Count = 885 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D21D7B36F8A5B028 - -Count = 886 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27629016BF1BB5EA4F - -Count = 887 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D00859A6CB1D3B6B - -Count = 888 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2709413AE9CE286CB6 - -Count = 889 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27CF3670CFB8D010B3 - -Count = 890 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273A61376E90FBC7EC - -Count = 891 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27FD402D9FB289840F - -Count = 892 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E664EB0E34E4BFDB08 - -Count = 893 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CBEE2788991FD9A5 - -Count = 894 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E4F7E486D9532224 - -Count = 895 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EB903D26EE06F5FF - -Count = 896 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E646DF70B00868B3BD - -Count = 897 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6887ACF285C1F06EF - -Count = 898 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6C1F630FCA4B46246 - -Count = 899 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E660F737DBFFB57459 - -Count = 900 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EC62FE33546AF6D3 - -Count = 901 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E624BC6732D8468A7B - -Count = 902 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6AFBFB5811A551A88 - -Count = 903 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E98628BDF7A210EB - -Count = 904 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6B364A18D6DC37CAD - -Count = 905 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E64C70A37077914979 - -Count = 906 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60B0466700132183E - -Count = 907 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6BA5E97583ABEE16A - -Count = 908 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E67A8CCDD4A00B5897 - -Count = 909 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E62D500EABFB82B5A0 - -Count = 910 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EFF8FBBBF21E6E3C - -Count = 911 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E61EBAD6BA6955926E - -Count = 912 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CD77682A3C530E3D - -Count = 913 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E66DDEF8E904EB5E74 - -Count = 914 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6DD744FCE6DC0833C - -Count = 915 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6F79B6BB4E47481FF - -Count = 916 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E62AF1CEAE48BEFFDA - -Count = 917 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6D797698667E043F3 - -Count = 918 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60EC9319EAD2D400C - -Count = 919 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6BE445C174E3D1A6B - -Count = 920 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60CDC130E9E95CB4F - -Count = 921 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6D59570419BA09C92 - -Count = 922 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E613E23A67ED58E097 - -Count = 923 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E6B57DC6C57337C8 - -Count = 924 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E621946737E701742B - -Count = 925 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC16EAF1576BD8ED2C - -Count = 926 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCB9EFD8EB1678EF81 - -Count = 927 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC96F61BE556341400 - -Count = 928 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9991C2456161C3DB - -Count = 929 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC34DE8FD3870F8599 - -Count = 930 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCFA7B304BD37830CB - -Count = 931 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCB3F7CF9F2BD35462 - -Count = 932 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC12F6C8B870D2427D - -Count = 933 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9E630150DB0DC0F7 - -Count = 934 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC56BD98515721BC5F - -Count = 935 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCDDBE4AE295322CAC - -Count = 936 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9B87D7DE78C526CF - -Count = 937 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCC1655EEEE2A44A89 - -Count = 938 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC3E715C13F8F67F5D - -Count = 939 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC790599138E552E1A - -Count = 940 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCC85F683BB5D9D74E - -Count = 941 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC088D32B72F6C6EB3 - -Count = 942 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC5F51F1C874E58384 - -Count = 943 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9DF904D87D795818 - -Count = 944 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC6CBB29D9E632A44A - -Count = 945 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBF769749B3343819 - -Count = 946 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC1FDF078A8B8C6850 - -Count = 947 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCAF75B0ADE2A7B518 - -Count = 948 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC859A94D76B13B7DB - -Count = 949 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC58F031CDC7D9C9FE - -Count = 950 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCA59696E5E88775D7 - -Count = 951 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC7CC8CEFD224A7628 - -Count = 952 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCCC45A374C15A2C4F - -Count = 953 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC7EDDEC6D11F2FD6B - -Count = 954 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCA7948F2214C7AAB6 - -Count = 955 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC61E3C504623FD6B3 - -Count = 956 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC94B482A54A1401EC - -Count = 957 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC539598546866420F - -Count = 958 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC9AB6F46C910247FA - -Count = 959 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC35B3DDD0ECA24557 - -Count = 960 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC1AAA1EDEACEEBED6 - -Count = 961 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC15CDC77E9BBB690D - -Count = 962 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCB8828AE87DD52F4F - -Count = 963 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC7627357029A29A1D - -Count = 964 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC3FABCAA4D109FEB4 - -Count = 965 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC9EAACD838A08E8AB - -Count = 966 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC123F046B21D76A21 - -Count = 967 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCDAE19D6AADFB1689 - -Count = 968 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC51E24FD96FE8867A - -Count = 969 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC17DBD2E5821F8C19 - -Count = 970 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC4D395BD5187EE05F - -Count = 971 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCB22D5928022CD58B - -Count = 972 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF5599C28748F84CC - -Count = 973 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC44036D004F037D98 - -Count = 974 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC84D1378CD5B6C465 - -Count = 975 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCD30DF4F38E3F2952 - -Count = 976 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC11A501E387A3F2CE - -Count = 977 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCE0E72CE21CE80E9C - -Count = 978 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC332A927249EE92CF - -Count = 979 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC938302B17156C286 - -Count = 980 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC2329B596187D1FCE - -Count = 981 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC09C691EC91C91D0D - -Count = 982 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCD4AC34F63D036328 - -Count = 983 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC29CA93DE125DDF01 - -Count = 984 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF094CBC6D890DCFE - -Count = 985 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC4019A64F3B808699 - -Count = 986 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF281E956EB2857BD - -Count = 987 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC2BC88A19EE1D0060 - -Count = 988 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCEDBFC03F98E57C65 - -Count = 989 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC18E8879EB0CEAB3A - -Count = 990 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCDFC99D6F92BCE8D9 - -Count = 991 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B40FE4CF065DC957E - -Count = 992 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BEFFB654C187C97D3 - -Count = 993 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC0E2A64258306C52 - -Count = 994 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCF857FE26F65BB89 - -Count = 995 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B62CA3274890BFDCB - -Count = 996 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BAC6F8DECDD7C4899 - -Count = 997 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BE5E3723825D72C30 - -Count = 998 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B44E2751F7ED63A2F - -Count = 999 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC877BCF7D509B8A5 - -Count = 1000 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B00A925F65925C40D - -Count = 1001 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B8BAAF7459B3654FE - -Count = 1002 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCD936A7976C15E9D - -Count = 1003 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9771E349ECA032DB - -Count = 1004 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B6865E1B4F6F2070F - -Count = 1005 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B2F1124B480515648 - -Count = 1006 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9E4BD59CBBDDAF1C - -Count = 1007 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5E998F10216816E1 - -Count = 1008 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B09454C6F7AE1FBD6 - -Count = 1009 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCBEDB97F737D204A - -Count = 1010 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B3AAF947EE836DC18 - -Count = 1011 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BE9622AEEBD30404B - -Count = 1012 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B49CBBA2D85881002 - -Count = 1013 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF9610D0AECA3CD4A - -Count = 1014 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BD38E29706517CF89 - -Count = 1015 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B0EE48C6AC9DDB1AC - -Count = 1016 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF3822B42E6830D85 - -Count = 1017 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B2ADC735A2C4E0E7A - -Count = 1018 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9A511ED3CF5E541D - -Count = 1019 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B28C951CA1FF68539 - -Count = 1020 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF18032851AC3D2E4 - -Count = 1021 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B37F778A36C3BAEE1 - -Count = 1022 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC2A03F02441079BE - -Count = 1023 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B058125F366623A5D - -Count = 1024 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AC550DC80ABDC9E65 - -Count = 1025 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A6A55F53CD67C9CC8 - -Count = 1026 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A454C363296306749 - -Count = 1027 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4A2BEF92A165B092 - -Count = 1028 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AE764A204470BF6D0 - -Count = 1029 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A29C11D9C137C4382 - -Count = 1030 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A604DE248EBD7272B - -Count = 1031 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AC14CE56FB0D63134 - -Count = 1032 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4DD92C871B09B3BE - -Count = 1033 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8507B5869725CF16 - -Count = 1034 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A0E04673555365FE5 - -Count = 1035 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A483DFA09B8C15586 - -Count = 1036 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A12DF733922A039C0 - -Count = 1037 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AEDCB71C438F20C14 - -Count = 1038 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAABFB4C44E515D53 - -Count = 1039 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1BE545EC75DDA407 - -Count = 1040 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ADB371F60EF681DFA - -Count = 1041 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8CEBDC1FB4E1F0CD - -Count = 1042 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4E43290FBD7D2B51 - -Count = 1043 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ABF01040E2636D703 - -Count = 1044 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A6CCCBA9E73304B50 - -Count = 1045 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ACC652A5D4B881B19 - -Count = 1046 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A7CCF9D7A22A3C651 - -Count = 1047 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A5620B900AB17C492 - -Count = 1048 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8B4A1C1A07DDBAB7 - -Count = 1049 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A762CBB322883069E - -Count = 1050 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAF72E32AE24E0561 - -Count = 1051 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1FFF8EA3015E5F06 - -Count = 1052 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAD67C1BAD1F68E22 - -Count = 1053 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A742EA2F5D4C3D9FF - -Count = 1054 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AB259E8D3A23BA5FA - -Count = 1055 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A470EAF728A1072A5 - -Count = 1056 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A802FB583A8623146 - -Count = 1057 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16129984AAE23DA1FE - -Count = 1058 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16BD9CAD169F9DA353 - -Count = 1059 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1692856E18DFD158D2 - -Count = 1060 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169DE2B7B8E8848F09 - -Count = 1061 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1630ADFA2E0EEAC94B - -Count = 1062 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16FE0845B65A9D7C19 - -Count = 1063 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16B784BA62A23618B0 - -Count = 1064 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A161685BD45F9370EAF - -Count = 1065 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304050607 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169A1074AD52E88C25 - -Count = 1066 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1652CEEDACDEC4F08D - -Count = 1067 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506070809 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16D9CD3F1F1CD7607E - -Count = 1068 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169FF4A223F1206A1D - -Count = 1069 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16C5162B136B41065B - -Count = 1070 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A163A0229EE7113338F - -Count = 1071 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A167D76ECEE07B062C8 - -Count = 1072 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16CC2C1DC63C3C9B9C - -Count = 1073 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A160CFE474AA6892261 - -Count = 1074 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A165B228435FD00CF56 - -Count = 1075 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16998A7125F49C14CA - -Count = 1076 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1668C85C246FD7E898 - -Count = 1077 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16BB05E2B43AD174CB - -Count = 1078 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A161BAC727702692482 - -Count = 1079 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16AB06C5506B42F9CA - -Count = 1080 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1681E9E12AE2F6FB09 - -Count = 1081 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A165C8344304E3C852C - -Count = 1082 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16A1E5E31861623905 - -Count = 1083 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1678BBBB00ABAF3AFA - -Count = 1084 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16C836D68948BF609D - -Count = 1085 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A167AAE99909817B1B9 - -Count = 1086 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16A3E7FADF9D22E664 - -Count = 1087 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A166590B0F9EBDA9A61 - -Count = 1088 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1690C7F758C3F14D3E - -Count = 1089 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1657E6EDA9E1830EDD - +Count = 1 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = +CT = F9F52C3201D8EE81 + +Count = 2 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00 +CT = 56F0058E7C78EC2C + +Count = 3 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001 +CT = 79E9C6803C3417AD + +Count = 4 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102 +CT = 768E1F200B61C076 + +Count = 5 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203 +CT = DBC152B6ED0F8634 + +Count = 6 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304 +CT = 1564ED2EB9783366 + +Count = 7 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405 +CT = 5CE812FA41D357CF + +Count = 8 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506 +CT = FDE915DD1AD241D0 + +Count = 9 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304050607 +CT = 717CDC35B10DC35A + +Count = 10 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708 +CT = B9A245343D21BFF2 + +Count = 11 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506070809 +CT = 32A19787FF322F01 + +Count = 12 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A +CT = 74980ABB12C52562 + +Count = 13 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B +CT = 2E7A838B88A44924 + +Count = 14 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C +CT = D16E817692F67CF0 + +Count = 15 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D +CT = 961A4476E4552DB7 + +Count = 16 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E +CT = 2740B55EDFD9D4E3 + +Count = 17 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F +CT = E792EFD2456C6D1E + +Count = 18 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10 +CT = B04E2CAD1EE58029 + +Count = 19 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 72E6D9BD17795BB5 + +Count = 20 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 83A4F4BC8C32A7E7 + +Count = 21 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 50694A2CD9343BB4 + +Count = 22 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = F0C0DAEFE18C6BFD + +Count = 23 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 406A6DC888A7B6B5 + +Count = 24 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 6A8549B20113B476 + +Count = 25 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = B7EFECA8ADD9CA53 + +Count = 26 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 4A894B808287767A + +Count = 27 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 93D71398484A7585 + +Count = 28 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 235A7E11AB5A2FE2 + +Count = 29 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 91C231087BF2FEC6 + +Count = 30 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 488B52477EC7A91B + +Count = 31 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 8EFC1861083FD51E + +Count = 32 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 7BAB5FC020140241 + +Count = 33 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = BC8A4531026641A2 + +Count = 34 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = +CT = FE2C92E25CDDEBE2A5 + +Count = 35 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00 +CT = FE8397CBE0A04BE008 + +Count = 36 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001 +CT = FEAC8E08EEE0071B89 + +Count = 37 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102 +CT = FEA3E9D14ED752CC52 + +Count = 38 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203 +CT = FE0EA69CD8313C8A10 + +Count = 39 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304 +CT = FEC0032340654B3F42 + +Count = 40 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405 +CT = FE898FDC949DE05BEB + +Count = 41 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506 +CT = FE288EDBB3C6E14DF4 + +Count = 42 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304050607 +CT = FEA41B125B6D3ECF7E + +Count = 43 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708 +CT = FE6CC58B5AE112B3D6 + +Count = 44 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506070809 +CT = FEE7C659E923012325 + +Count = 45 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A +CT = FEA1FFC4D5CEF62946 + +Count = 46 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B +CT = FEFB1D4DE554974500 + +Count = 47 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C +CT = FE04094F184EC570D4 + +Count = 48 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D +CT = FE437D8A1838662193 + +Count = 49 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E +CT = FEF2277B3003EAD8C7 + +Count = 50 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F +CT = FE32F521BC995F613A + +Count = 51 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FE6529E2C3C2D68C0D + +Count = 52 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEA78117D3CB4A5791 + +Count = 53 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FE56C33AD25001ABC3 + +Count = 54 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FE850E844205073790 + +Count = 55 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FE25A714813DBF67D9 + +Count = 56 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FE950DA3A65494BA91 + +Count = 57 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEBFE287DCDD20B852 + +Count = 58 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FE628822C671EAC677 + +Count = 59 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FE9FEE85EE5EB47A5E + +Count = 60 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FE46B0DDF6947979A1 + +Count = 61 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEF63DB07F776923C6 + +Count = 62 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FE44A5FF66A7C1F2E2 + +Count = 63 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FE9DEC9C29A2F4A53F + +Count = 64 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FE5B9BD60FD40CD93A + +Count = 65 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEAECC91AEFC270E65 + +Count = 66 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FE69ED8B5FDE554D86 + +Count = 67 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = +CT = FEC9C5D02385265671AA + +Count = 68 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00 +CT = FEC96AD50A395BF67307 + +Count = 69 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001 +CT = FEC945CCC9371BBA8886 + +Count = 70 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102 +CT = FEC94AAB10972CEF5F5D + +Count = 71 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203 +CT = FEC9E7E45D01CA81191F + +Count = 72 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304 +CT = FEC92941E2999EF6AC4D + +Count = 73 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405 +CT = FEC960CD1D4D665DC8E4 + +Count = 74 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506 +CT = FEC9C1CC1A6A3D5CDEFB + +Count = 75 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304050607 +CT = FEC94D59D38296835C71 + +Count = 76 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708 +CT = FEC985874A831AAF20D9 + +Count = 77 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506070809 +CT = FEC90E849830D8BCB02A + +Count = 78 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A +CT = FEC948BD050C354BBA49 + +Count = 79 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B +CT = FEC9125F8C3CAF2AD60F + +Count = 80 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C +CT = FEC9ED4B8EC1B578E3DB + +Count = 81 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D +CT = FEC9AA3F4BC1C3DBB29C + +Count = 82 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E +CT = FEC91B65BAE9F8574BC8 + +Count = 83 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC9DBB7E06562E2F235 + +Count = 84 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC98C6B231A396B1F02 + +Count = 85 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC94EC3D60A30F7C49E + +Count = 86 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC9BF81FB0BABBC38CC + +Count = 87 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC96C4C459BFEBAA49F + +Count = 88 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC9CCE5D558C602F4D6 + +Count = 89 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC97C4F627FAF29299E + +Count = 90 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC956A04605269D2B5D + +Count = 91 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC98BCAE31F8A575578 + +Count = 92 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC976AC4437A509E951 + +Count = 93 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC9AFF21C2F6FC4EAAE + +Count = 94 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC91F7F71A68CD4B0C9 + +Count = 95 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC9ADE73EBF5C7C61ED + +Count = 96 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC974AE5DF059493630 + +Count = 97 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC9B2D917D62FB14A35 + +Count = 98 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC9478E5077079A9D6A + +Count = 99 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC980AF4A8625E8DE89 + +Count = 100 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = +CT = FEC9411BC7AA32DC76BB7D + +Count = 101 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00 +CT = FEC941B4C2838EA1D6B9D0 + +Count = 102 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001 +CT = FEC9419BDB4080E19A4251 + +Count = 103 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102 +CT = FEC94194BC9920D6CF958A + +Count = 104 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203 +CT = FEC94139F3D4B630A1D3C8 + +Count = 105 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304 +CT = FEC941F7566B2E64D6669A + +Count = 106 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405 +CT = FEC941BEDA94FA9C7D0233 + +Count = 107 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506 +CT = FEC9411FDB93DDC77C142C + +Count = 108 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304050607 +CT = FEC941934E5A356CA396A6 + +Count = 109 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708 +CT = FEC9415B90C334E08FEA0E + +Count = 110 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506070809 +CT = FEC941D0931187229C7AFD + +Count = 111 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A +CT = FEC94196AA8CBBCF6B709E + +Count = 112 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B +CT = FEC941CC48058B550A1CD8 + +Count = 113 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C +CT = FEC941335C07764F58290C + +Count = 114 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D +CT = FEC9417428C27639FB784B + +Count = 115 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941C572335E0277811F + +Count = 116 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC94105A069D298C238E2 + +Count = 117 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941527CAAADC34BD5D5 + +Count = 118 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC94190D45FBDCAD70E49 + +Count = 119 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941619672BC519CF21B + +Count = 120 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941B25BCC2C049A6E48 + +Count = 121 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC94112F25CEF3C223E01 + +Count = 122 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941A258EBC85509E349 + +Count = 123 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC94188B7CFB2DCBDE18A + +Count = 124 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC94155DD6AA870779FAF + +Count = 125 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941A8BBCD805F292386 + +Count = 126 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC94171E5959895E42079 + +Count = 127 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941C168F81176F47A1E + +Count = 128 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC94173F0B708A65CAB3A + +Count = 129 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941AAB9D447A369FCE7 + +Count = 130 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC9416CCE9E61D59180E2 + +Count = 131 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC9419999D9C0FDBA57BD + +Count = 132 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC9415EB8C331DFC8145E + +Count = 133 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = +CT = FEC941479E83007EEF580F5C + +Count = 134 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00 +CT = FEC94147318629C292F80DF1 + +Count = 135 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001 +CT = FEC941471E9FEACCD2B4F670 + +Count = 136 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102 +CT = FEC9414711F8336CE5E121AB + +Count = 137 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203 +CT = FEC94147BCB77EFA038F67E9 + +Count = 138 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304 +CT = FEC941477212C16257F8D2BB + +Count = 139 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405 +CT = FEC941473B9E3EB6AF53B612 + +Count = 140 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506 +CT = FEC941479A9F3991F452A00D + +Count = 141 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304050607 +CT = FEC94147160AF0795F8D2287 + +Count = 142 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708 +CT = FEC94147DED46978D3A15E2F + +Count = 143 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506070809 +CT = FEC9414755D7BBCB11B2CEDC + +Count = 144 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A +CT = FEC9414713EE26F7FC45C4BF + +Count = 145 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B +CT = FEC94147490CAFC76624A8F9 + +Count = 146 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C +CT = FEC94147B618AD3A7C769D2D + +Count = 147 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D +CT = FEC94147F16C683A0AD5CC6A + +Count = 148 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E +CT = FEC94147403699123159353E + +Count = 149 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC9414780E4C39EABEC8CC3 + +Count = 150 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC94147D73800E1F06561F4 + +Count = 151 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941471590F5F1F9F9BA68 + +Count = 152 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC94147E4D2D8F062B2463A + +Count = 153 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC94147371F666037B4DA69 + +Count = 154 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC9414797B6F6A30F0C8A20 + +Count = 155 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC94147271C418466275768 + +Count = 156 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470DF365FEEF9355AB + +Count = 157 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC94147D099C0E443592B8E + +Count = 158 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941472DFF67CC6C0797A7 + +Count = 159 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC94147F4A13FD4A6CA9458 + +Count = 160 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC94147442C525D45DACE3F + +Count = 161 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC94147F6B41D4495721F1B + +Count = 162 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941472FFD7E0B904748C6 + +Count = 163 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC94147E98A342DE6BF34C3 + +Count = 164 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941471CDD738CCE94E39C + +Count = 165 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC94147DBFC697DECE6A07F + +Count = 166 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = +CT = FEC941470C278F4DD8B1E42763 + +Count = 167 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00 +CT = FEC941470C888A6464CC4425CE + +Count = 168 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001 +CT = FEC941470CA793A76A8C08DE4F + +Count = 169 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102 +CT = FEC941470CA8F47ECABB5D0994 + +Count = 170 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203 +CT = FEC941470C05BB335C5D334FD6 + +Count = 171 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304 +CT = FEC941470CCB1E8CC40944FA84 + +Count = 172 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405 +CT = FEC941470C82927310F1EF9E2D + +Count = 173 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506 +CT = FEC941470C23937437AAEE8832 + +Count = 174 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304050607 +CT = FEC941470CAF06BDDF01310AB8 + +Count = 175 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708 +CT = FEC941470C67D824DE8D1D7610 + +Count = 176 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506070809 +CT = FEC941470CECDBF66D4F0EE6E3 + +Count = 177 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A +CT = FEC941470CAAE26B51A2F9EC80 + +Count = 178 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B +CT = FEC941470CF000E261389880C6 + +Count = 179 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C +CT = FEC941470C0F14E09C22CAB512 + +Count = 180 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D +CT = FEC941470C4860259C5469E455 + +Count = 181 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CF93AD4B46FE51D01 + +Count = 182 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470C39E88E38F550A4FC + +Count = 183 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470C6E344D47AED949CB + +Count = 184 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CAC9CB857A7459257 + +Count = 185 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470C5DDE95563C0E6E05 + +Count = 186 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470C8E132BC66908F256 + +Count = 187 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470C2EBABB0551B0A21F + +Count = 188 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470C9E100C22389B7F57 + +Count = 189 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB4FF2858B12F7D94 + +Count = 190 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470C69958D421DE503B1 + +Count = 191 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470C94F32A6A32BBBF98 + +Count = 192 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470C4DAD7272F876BC67 + +Count = 193 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CFD201FFB1B66E600 + +Count = 194 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470C4FB850E2CBCE3724 + +Count = 195 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470C96F133ADCEFB60F9 + +Count = 196 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470C5086798BB8031CFC + +Count = 197 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CA5D13E2A9028CBA3 + +Count = 198 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470C62F024DBB25A8840 + +Count = 199 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = +CT = FEC941470CB8E24205EEF8093C08 + +Count = 200 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00 +CT = FEC941470CB84D472C5285A93EA5 + +Count = 201 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001 +CT = FEC941470CB8625EEF5CC5E5C524 + +Count = 202 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102 +CT = FEC941470CB86D3936FCF2B012FF + +Count = 203 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203 +CT = FEC941470CB8C0767B6A14DE54BD + +Count = 204 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304 +CT = FEC941470CB80ED3C4F240A9E1EF + +Count = 205 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405 +CT = FEC941470CB8475F3B26B8028546 + +Count = 206 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506 +CT = FEC941470CB8E65E3C01E3039359 + +Count = 207 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304050607 +CT = FEC941470CB86ACBF5E948DC11D3 + +Count = 208 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708 +CT = FEC941470CB8A2156CE8C4F06D7B + +Count = 209 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506070809 +CT = FEC941470CB82916BE5B06E3FD88 + +Count = 210 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A +CT = FEC941470CB86F2F2367EB14F7EB + +Count = 211 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B +CT = FEC941470CB835CDAA5771759BAD + +Count = 212 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C +CT = FEC941470CB8CAD9A8AA6B27AE79 + +Count = 213 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB88DAD6DAA1D84FF3E + +Count = 214 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB83CF79C822608066A + +Count = 215 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB8FC25C60EBCBDBF97 + +Count = 216 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB8ABF90571E73452A0 + +Count = 217 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB86951F061EEA8893C + +Count = 218 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB89813DD6075E3756E + +Count = 219 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB84BDE63F020E5E93D + +Count = 220 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB8EB77F333185DB974 + +Count = 221 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB85BDD44147176643C + +Count = 222 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB87132606EF8C266FF + +Count = 223 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB8AC58C574540818DA + +Count = 224 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB8513E625C7B56A4F3 + +Count = 225 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB888603A44B19BA70C + +Count = 226 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB838ED57CD528BFD6B + +Count = 227 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB88A7518D482232C4F + +Count = 228 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB8533C7B9B87167B92 + +Count = 229 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB8954B31BDF1EE0797 + +Count = 230 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB8601C761CD9C5D0C8 + +Count = 231 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB8A73D6CEDFBB7932B + +Count = 232 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = +CT = FEC941470CB85931CD20ED8103BD44 + +Count = 233 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00 +CT = FEC941470CB8599EC80951FCA3BFE9 + +Count = 234 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001 +CT = FEC941470CB859B1D1CA5FBCEF4468 + +Count = 235 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102 +CT = FEC941470CB859BEB613FF8BBA93B3 + +Count = 236 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203 +CT = FEC941470CB85913F95E696DD4D5F1 + +Count = 237 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304 +CT = FEC941470CB859DD5CE1F139A360A3 + +Count = 238 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405 +CT = FEC941470CB85994D01E25C108040A + +Count = 239 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506 +CT = FEC941470CB85935D119029A091215 + +Count = 240 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304050607 +CT = FEC941470CB859B944D0EA31D6909F + +Count = 241 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708 +CT = FEC941470CB859719A49EBBDFAEC37 + +Count = 242 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506070809 +CT = FEC941470CB859FA999B587FE97CC4 + +Count = 243 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A +CT = FEC941470CB859BCA00664921E76A7 + +Count = 244 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B +CT = FEC941470CB859E6428F54087F1AE1 + +Count = 245 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C +CT = FEC941470CB85919568DA9122D2F35 + +Count = 246 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB8595E2248A9648E7E72 + +Count = 247 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859EF78B9815F028726 + +Count = 248 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB8592FAAE30DC5B73EDB + +Count = 249 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859787620729E3ED3EC + +Count = 250 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859BADED56297A20870 + +Count = 251 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB8594B9CF8630CE9F422 + +Count = 252 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859985146F359EF6871 + +Count = 253 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB85938F8D63061573838 + +Count = 254 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB85988526117087CE570 + +Count = 255 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859A2BD456D81C8E7B3 + +Count = 256 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB8597FD7E0772D029996 + +Count = 257 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB85982B1475F025C25BF + +Count = 258 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB8595BEF1F47C8912640 + +Count = 259 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859EB6272CE2B817C27 + +Count = 260 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB85959FA3DD7FB29AD03 + +Count = 261 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB85980B35E98FE1CFADE + +Count = 262 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB85946C414BE88E486DB + +Count = 263 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859B393531FA0CF5184 + +Count = 264 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB85974B249EE82BD1267 + +Count = 265 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = +CT = FEC941470CB859D7A1F29672CF3310E0 + +Count = 266 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00 +CT = FEC941470CB859D70EF7BFCEB293124D + +Count = 267 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001 +CT = FEC941470CB859D721EE7CC0F2DFE9CC + +Count = 268 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102 +CT = FEC941470CB859D72E89A560C58A3E17 + +Count = 269 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203 +CT = FEC941470CB859D783C6E8F623E47855 + +Count = 270 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304 +CT = FEC941470CB859D74D63576E7793CD07 + +Count = 271 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405 +CT = FEC941470CB859D704EFA8BA8F38A9AE + +Count = 272 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506 +CT = FEC941470CB859D7A5EEAF9DD439BFB1 + +Count = 273 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304050607 +CT = FEC941470CB859D7297B66757FE63D3B + +Count = 274 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708 +CT = FEC941470CB859D7E1A5FF74F3CA4193 + +Count = 275 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506070809 +CT = FEC941470CB859D76AA62DC731D9D160 + +Count = 276 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A +CT = FEC941470CB859D72C9FB0FBDC2EDB03 + +Count = 277 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B +CT = FEC941470CB859D7767D39CB464FB745 + +Count = 278 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D789693B365C1D8291 + +Count = 279 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D7CE1DFE362ABED3D6 + +Count = 280 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D77F470F1E11322A82 + +Count = 281 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D7BF9555928B87937F + +Count = 282 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D7E84996EDD00E7E48 + +Count = 283 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D72AE163FDD992A5D4 + +Count = 284 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D7DBA34EFC42D95986 + +Count = 285 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D7086EF06C17DFC5D5 + +Count = 286 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D7A8C760AF2F67959C + +Count = 287 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D7186DD788464C48D4 + +Count = 288 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D73282F3F2CFF84A17 + +Count = 289 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D7EFE856E863323432 + +Count = 290 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D7128EF1C04C6C881B + +Count = 291 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D7CBD0A9D886A18BE4 + +Count = 292 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D77B5DC45165B1D183 + +Count = 293 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D7C9C58B48B51900A7 + +Count = 294 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D7108CE807B02C577A + +Count = 295 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D7D6FBA221C6D42B7F + +Count = 296 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D723ACE580EEFFFC20 + +Count = 297 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D7E48DFF71CC8DBFC3 + +Count = 298 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = +CT = FEC941470CB859D7354BDE6B3DDA94AA48 + +Count = 299 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00 +CT = FEC941470CB859D735E4DB4281A734A8E5 + +Count = 300 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001 +CT = FEC941470CB859D735CBC2818FE7785364 + +Count = 301 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102 +CT = FEC941470CB859D735C4A5582FD02D84BF + +Count = 302 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203 +CT = FEC941470CB859D73569EA15B93643C2FD + +Count = 303 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304 +CT = FEC941470CB859D735A74FAA21623477AF + +Count = 304 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405 +CT = FEC941470CB859D735EEC355F59A9F1306 + +Count = 305 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506 +CT = FEC941470CB859D7354FC252D2C19E0519 + +Count = 306 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304050607 +CT = FEC941470CB859D735C3579B3A6A418793 + +Count = 307 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708 +CT = FEC941470CB859D7350B89023BE66DFB3B + +Count = 308 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506070809 +CT = FEC941470CB859D735808AD088247E6BC8 + +Count = 309 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A +CT = FEC941470CB859D735C6B34DB4C98961AB + +Count = 310 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B +CT = FEC941470CB859D7359C51C48453E80DED + +Count = 311 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D7356345C67949BA3839 + +Count = 312 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735243103793F19697E + +Count = 313 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735956BF2510495902A + +Count = 314 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D73555B9A8DD9E2029D7 + +Count = 315 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D73502656BA2C5A9C4E0 + +Count = 316 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735C0CD9EB2CC351F7C + +Count = 317 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735318FB3B3577EE32E + +Count = 318 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735E2420D2302787F7D + +Count = 319 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D73542EB9DE03AC02F34 + +Count = 320 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735F2412AC753EBF27C + +Count = 321 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735D8AE0EBDDA5FF0BF + +Count = 322 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D73505C4ABA776958E9A + +Count = 323 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735F8A20C8F59CB32B3 + +Count = 324 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D73521FC54979306314C + +Count = 325 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D7359171391E70166B2B + +Count = 326 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D73523E97607A0BEBA0F + +Count = 327 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735FAA01548A58BEDD2 + +Count = 328 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D7353CD75F6ED37391D7 + +Count = 329 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735C98018CFFB584688 + +Count = 330 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D7350EA1023ED92A056B + +Count = 331 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = +CT = FEC941470CB859D735256D1107BAA5D56B3C + +Count = 332 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00 +CT = FEC941470CB859D73525C2142E06D8756991 + +Count = 333 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001 +CT = FEC941470CB859D73525ED0DED0898399210 + +Count = 334 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102 +CT = FEC941470CB859D73525E26A34A8AF6C45CB + +Count = 335 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203 +CT = FEC941470CB859D735254F25793E49020389 + +Count = 336 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304 +CT = FEC941470CB859D735258180C6A61D75B6DB + +Count = 337 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405 +CT = FEC941470CB859D73525C80C3972E5DED272 + +Count = 338 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506 +CT = FEC941470CB859D73525690D3E55BEDFC46D + +Count = 339 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304050607 +CT = FEC941470CB859D73525E598F7BD150046E7 + +Count = 340 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708 +CT = FEC941470CB859D735252D466EBC992C3A4F + +Count = 341 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506070809 +CT = FEC941470CB859D73525A645BC0F5B3FAABC + +Count = 342 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A +CT = FEC941470CB859D73525E07C2133B6C8A0DF + +Count = 343 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B +CT = FEC941470CB859D73525BA9EA8032CA9CC99 + +Count = 344 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D73525458AAAFE36FBF94D + +Count = 345 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D7352502FE6FFE4058A80A + +Count = 346 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D73525B3A49ED67BD4515E + +Count = 347 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735257376C45AE161E8A3 + +Count = 348 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D7352524AA0725BAE80594 + +Count = 349 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D73525E602F235B374DE08 + +Count = 350 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735251740DF34283F225A + +Count = 351 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D73525C48D61A47D39BE09 + +Count = 352 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735256424F1674581EE40 + +Count = 353 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D73525D48E46402CAA3308 + +Count = 354 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D73525FE61623AA51E31CB + +Count = 355 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D73525230BC72009D44FEE + +Count = 356 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D73525DE6D6008268AF3C7 + +Count = 357 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D7352507333810EC47F038 + +Count = 358 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D73525B7BE55990F57AA5F + +Count = 359 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D7352505261A80DFFF7B7B + +Count = 360 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D73525DC6F79CFDACA2CA6 + +Count = 361 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735251A1833E9AC3250A3 + +Count = 362 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D73525EF4F7448841987FC + +Count = 363 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D73525286E6EB9A66BC41F + +Count = 364 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = +CT = FEC941470CB859D735255BFCFBA78DDD0631FE + +Count = 365 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00 +CT = FEC941470CB859D735255B53FE8E31A0A63353 + +Count = 366 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001 +CT = FEC941470CB859D735255B7CE74D3FE0EAC8D2 + +Count = 367 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102 +CT = FEC941470CB859D735255B7380949FD7BF1F09 + +Count = 368 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203 +CT = FEC941470CB859D735255BDECFD90931D1594B + +Count = 369 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304 +CT = FEC941470CB859D735255B106A669165A6EC19 + +Count = 370 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405 +CT = FEC941470CB859D735255B59E699459D0D88B0 + +Count = 371 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506 +CT = FEC941470CB859D735255BF8E79E62C60C9EAF + +Count = 372 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304050607 +CT = FEC941470CB859D735255B7472578A6DD31C25 + +Count = 373 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708 +CT = FEC941470CB859D735255BBCACCE8BE1FF608D + +Count = 374 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506070809 +CT = FEC941470CB859D735255B37AF1C3823ECF07E + +Count = 375 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A +CT = FEC941470CB859D735255B71968104CE1BFA1D + +Count = 376 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B2B740834547A965B + +Count = 377 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255BD4600AC94E28A38F + +Count = 378 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B9314CFC9388BF2C8 + +Count = 379 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B224E3EE103070B9C + +Count = 380 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255BE29C646D99B2B261 + +Count = 381 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255BB540A712C23B5F56 + +Count = 382 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B77E85202CBA784CA + +Count = 383 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B86AA7F0350EC7898 + +Count = 384 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B5567C19305EAE4CB + +Count = 385 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255BF5CE51503D52B482 + +Count = 386 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B4564E677547969CA + +Count = 387 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B6F8BC20DDDCD6B09 + +Count = 388 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255BB2E167177107152C + +Count = 389 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B4F87C03F5E59A905 + +Count = 390 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B96D998279494AAFA + +Count = 391 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B2654F5AE7784F09D + +Count = 392 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B94CCBAB7A72C21B9 + +Count = 393 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B4D85D9F8A2197664 + +Count = 394 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B8BF293DED4E10A61 + +Count = 395 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B7EA5D47FFCCADD3E + +Count = 396 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255BB984CE8EDEB89EDD + +Count = 397 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = +CT = FEC941470CB859D735255B80B658144E4BAC29D0 + +Count = 398 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00 +CT = FEC941470CB859D735255B80195D3DF2360C2B7D + +Count = 399 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001 +CT = FEC941470CB859D735255B803644FEFC7640D0FC + +Count = 400 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102 +CT = FEC941470CB859D735255B803923275C41150727 + +Count = 401 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203 +CT = FEC941470CB859D735255B80946C6ACAA77B4165 + +Count = 402 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304 +CT = FEC941470CB859D735255B805AC9D552F30CF437 + +Count = 403 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405 +CT = FEC941470CB859D735255B8013452A860BA7909E + +Count = 404 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506 +CT = FEC941470CB859D735255B80B2442DA150A68681 + +Count = 405 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304050607 +CT = FEC941470CB859D735255B803ED1E449FB79040B + +Count = 406 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708 +CT = FEC941470CB859D735255B80F60F7D48775578A3 + +Count = 407 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506070809 +CT = FEC941470CB859D735255B807D0CAFFBB546E850 + +Count = 408 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A +CT = FEC941470CB859D735255B803B3532C758B1E233 + +Count = 409 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B8061D7BBF7C2D08E75 + +Count = 410 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B809EC3B90AD882BBA1 + +Count = 411 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80D9B77C0AAE21EAE6 + +Count = 412 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B8068ED8D2295AD13B2 + +Count = 413 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80A83FD7AE0F18AA4F + +Count = 414 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80FFE314D154914778 + +Count = 415 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B803D4BE1C15D0D9CE4 + +Count = 416 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80CC09CCC0C64660B6 + +Count = 417 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B801FC472509340FCE5 + +Count = 418 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80BF6DE293ABF8ACAC + +Count = 419 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B800FC755B4C2D371E4 + +Count = 420 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80252871CE4B677327 + +Count = 421 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80F842D4D4E7AD0D02 + +Count = 422 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80052473FCC8F3B12B + +Count = 423 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80DC7A2BE4023EB2D4 + +Count = 424 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B806CF7466DE12EE8B3 + +Count = 425 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80DE6F097431863997 + +Count = 426 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B8007266A3B34B36E4A + +Count = 427 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80C151201D424B124F + +Count = 428 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80340667BC6A60C510 + +Count = 429 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80F3277D4D481286F3 + +Count = 430 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = +CT = FEC941470CB859D735255B80669A87B729D1F56CAC + +Count = 431 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00 +CT = FEC941470CB859D735255B806635829E95AC556E01 + +Count = 432 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001 +CT = FEC941470CB859D735255B80661A9B5D9BEC199580 + +Count = 433 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102 +CT = FEC941470CB859D735255B806615FC843BDB4C425B + +Count = 434 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203 +CT = FEC941470CB859D735255B8066B8B3C9AD3D220419 + +Count = 435 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304 +CT = FEC941470CB859D735255B8066761676356955B14B + +Count = 436 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405 +CT = FEC941470CB859D735255B80663F9A89E191FED5E2 + +Count = 437 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506 +CT = FEC941470CB859D735255B80669E9B8EC6CAFFC3FD + +Count = 438 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304050607 +CT = FEC941470CB859D735255B8066120E472E61204177 + +Count = 439 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708 +CT = FEC941470CB859D735255B8066DAD0DE2FED0C3DDF + +Count = 440 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506070809 +CT = FEC941470CB859D735255B806651D30C9C2F1FAD2C + +Count = 441 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A +CT = FEC941470CB859D735255B806617EA91A0C2E8A74F + +Count = 442 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80664D0818905889CB09 + +Count = 443 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B8066B21C1A6D42DBFEDD + +Count = 444 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B8066F568DF6D3478AF9A + +Count = 445 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B806644322E450FF456CE + +Count = 446 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B806684E074C99541EF33 + +Count = 447 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B8066D33CB7B6CEC80204 + +Count = 448 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B8066119442A6C754D998 + +Count = 449 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B8066E0D66FA75C1F25CA + +Count = 450 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B8066331BD1370919B999 + +Count = 451 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B806693B241F431A1E9D0 + +Count = 452 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80662318F6D3588A3498 + +Count = 453 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B806609F7D2A9D13E365B + +Count = 454 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B8066D49D77B37DF4487E + +Count = 455 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B806629FBD09B52AAF457 + +Count = 456 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B8066F0A588839867F7A8 + +Count = 457 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80664028E50A7B77ADCF + +Count = 458 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B8066F2B0AA13ABDF7CEB + +Count = 459 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80662BF9C95CAEEA2B36 + +Count = 460 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B8066ED8E837AD8125733 + +Count = 461 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B806618D9C4DBF039806C + +Count = 462 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B8066DFF8DE2AD24BC38F + +Count = 463 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = +CT = FEC941470CB859D735255B80663E379995F290E84795 + +Count = 464 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00 +CT = FEC941470CB859D735255B80663E989CBC4EED484538 + +Count = 465 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001 +CT = FEC941470CB859D735255B80663EB7857F40AD04BEB9 + +Count = 466 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102 +CT = FEC941470CB859D735255B80663EB8E2A6E09A516962 + +Count = 467 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203 +CT = FEC941470CB859D735255B80663E15ADEB767C3F2F20 + +Count = 468 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304 +CT = FEC941470CB859D735255B80663EDB0854EE28489A72 + +Count = 469 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405 +CT = FEC941470CB859D735255B80663E9284AB3AD0E3FEDB + +Count = 470 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E3385AC1D8BE2E8C4 + +Count = 471 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663EBF1065F5203D6A4E + +Count = 472 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E77CEFCF4AC1116E6 + +Count = 473 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663EFCCD2E476E028615 + +Count = 474 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663EBAF4B37B83F58C76 + +Count = 475 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663EE0163A4B1994E030 + +Count = 476 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E1F0238B603C6D5E4 + +Count = 477 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E5876FDB6756584A3 + +Count = 478 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663EE92C0C9E4EE97DF7 + +Count = 479 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E29FE5612D45CC40A + +Count = 480 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E7E22956D8FD5293D + +Count = 481 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663EBC8A607D8649F2A1 + +Count = 482 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E4DC84D7C1D020EF3 + +Count = 483 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E9E05F3EC480492A0 + +Count = 484 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E3EAC632F70BCC2E9 + +Count = 485 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E8E06D40819971FA1 + +Count = 486 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663EA4E9F07290231D62 + +Count = 487 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E798355683CE96347 + +Count = 488 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E84E5F24013B7DF6E + +Count = 489 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E5DBBAA58D97ADC91 + +Count = 490 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663EED36C7D13A6A86F6 + +Count = 491 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E5FAE88C8EAC257D2 + +Count = 492 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E86E7EB87EFF7000F + +Count = 493 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E4090A1A1990F7C0A + +Count = 494 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663EB5C7E600B124AB55 + +Count = 495 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E72E6FCF19356E8B6 + +Count = 496 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = +CT = FEC941470CB859D735255B80663E80CA51659B586156DC + +Count = 497 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00 +CT = FEC941470CB859D735255B80663E8065544C2725C15471 + +Count = 498 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001 +CT = FEC941470CB859D735255B80663E804A4D8F29658DAFF0 + +Count = 499 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102 +CT = FEC941470CB859D735255B80663E80452A568952D8782B + +Count = 500 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203 +CT = FEC941470CB859D735255B80663E80E8651B1FB4B63E69 + +Count = 501 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304 +CT = FEC941470CB859D735255B80663E8026C0A487E0C18B3B + +Count = 502 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405 +CT = FEC941470CB859D735255B80663E806F4C5B53186AEF92 + +Count = 503 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E80CE4D5C74436BF98D + +Count = 504 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E8042D8959CE8B47B07 + +Count = 505 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E808A060C9D649807AF + +Count = 506 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E800105DE2EA68B975C + +Count = 507 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E80473C43124B7C9D3F + +Count = 508 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E801DDECA22D11DF179 + +Count = 509 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E80E2CAC8DFCB4FC4AD + +Count = 510 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E80A5BE0DDFBDEC95EA + +Count = 511 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E8014E4FCF786606CBE + +Count = 512 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E80D436A67B1CD5D543 + +Count = 513 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E8083EA6504475C3874 + +Count = 514 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E80414290144EC0E3E8 + +Count = 515 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E80B000BD15D58B1FBA + +Count = 516 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E8063CD0385808D83E9 + +Count = 517 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E80C3649346B835D3A0 + +Count = 518 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E8073CE2461D11E0EE8 + +Count = 519 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E805921001B58AA0C2B + +Count = 520 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E80844BA501F460720E + +Count = 521 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E80792D0229DB3ECE27 + +Count = 522 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E80A0735A3111F3CDD8 + +Count = 523 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E8010FE37B8F2E397BF + +Count = 524 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E80A26678A1224B469B + +Count = 525 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807B2F1BEE277E1146 + +Count = 526 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E80BD5851C851866D43 + +Count = 527 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E80480F166979ADBA1C + +Count = 528 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E808F2E0C985BDFF9FF + +Count = 529 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = +CT = FEC941470CB859D735255B80663E807AB39D122E7B101B1A + +Count = 530 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00 +CT = FEC941470CB859D735255B80663E807A1C983B9206B019B7 + +Count = 531 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001 +CT = FEC941470CB859D735255B80663E807A3381F89C46FCE236 + +Count = 532 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102 +CT = FEC941470CB859D735255B80663E807A3CE6213C71A935ED + +Count = 533 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A91A96CAA97C773AF + +Count = 534 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A5F0CD332C3B0C6FD + +Count = 535 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A16802CE63B1BA254 + +Count = 536 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807AB7812BC1601AB44B + +Count = 537 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A3B14E229CBC536C1 + +Count = 538 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807AF3CA7B2847E94A69 + +Count = 539 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A78C9A99B85FADA9A + +Count = 540 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A3EF034A7680DD0F9 + +Count = 541 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A6412BD97F26CBCBF + +Count = 542 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A9B06BF6AE83E896B + +Count = 543 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807ADC727A6A9E9DD82C + +Count = 544 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A6D288B42A5112178 + +Count = 545 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807AADFAD1CE3FA49885 + +Count = 546 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807AFA2612B1642D75B2 + +Count = 547 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A388EE7A16DB1AE2E + +Count = 548 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807AC9CCCAA0F6FA527C + +Count = 549 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A1A017430A3FCCE2F + +Count = 550 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807ABAA8E4F39B449E66 + +Count = 551 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A0A0253D4F26F432E + +Count = 552 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A20ED77AE7BDB41ED + +Count = 553 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807AFD87D2B4D7113FC8 + +Count = 554 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A00E1759CF84F83E1 + +Count = 555 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807AD9BF2D843282801E + +Count = 556 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A6932400DD192DA79 + +Count = 557 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807ADBAA0F14013A0B5D + +Count = 558 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A02E36C5B040F5C80 + +Count = 559 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807AC494267D72F72085 + +Count = 560 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A31C361DC5ADCF7DA + +Count = 561 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807AF6E27B2D78AEB439 + +Count = 562 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = +CT = FEC941470CB859D735255B80663E807A63A849D541118342CC + +Count = 563 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63074CFCFD6C234061 + +Count = 564 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A6328553FF32C6FBBE0 + +Count = 565 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A632732E6531B3A6C3B + +Count = 566 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A638A7DABC5FD542A79 + +Count = 567 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A6344D8145DA9239F2B + +Count = 568 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A630D54EB895188FB82 + +Count = 569 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63AC55ECAE0A89ED9D + +Count = 570 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A6320C02546A1566F17 + +Count = 571 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63E81EBC472D7A13BF + +Count = 572 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63631D6EF4EF69834C + +Count = 573 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A632524F3C8029E892F + +Count = 574 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A637FC67AF898FFE569 + +Count = 575 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A6380D2780582ADD0BD + +Count = 576 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63C7A6BD05F40E81FA + +Count = 577 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A6376FC4C2DCF8278AE + +Count = 578 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63B62E16A15537C153 + +Count = 579 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63E1F2D5DE0EBE2C64 + +Count = 580 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63235A20CE0722F7F8 + +Count = 581 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D2180DCF9C690BAA + +Count = 582 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A6301D5B35FC96F97F9 + +Count = 583 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63A17C239CF1D7C7B0 + +Count = 584 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A6311D694BB98FC1AF8 + +Count = 585 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A633B39B0C11148183B + +Count = 586 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63E65315DBBD82661E + +Count = 587 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A631B35B2F392DCDA37 + +Count = 588 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63C26BEAEB5811D9C8 + +Count = 589 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A6372E68762BB0183AF + +Count = 590 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63C07EC87B6BA9528B + +Count = 591 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A631937AB346E9C0556 + +Count = 592 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63DF40E11218647953 + +Count = 593 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A632A17A6B3304FAE0C + +Count = 594 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63ED36BC42123DEDEF + +Count = 595 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = +CT = FEC941470CB859D735255B80663E807A63D56D03C2D7ECE3838B + +Count = 596 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D5C206EB6B91438126 + +Count = 597 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D5ED1F2865D10F7AA7 + +Count = 598 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D5E278F1C5E65AAD7C + +Count = 599 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D54F37BC530034EB3E + +Count = 600 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D5819203CB54435E6C + +Count = 601 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D5C81EFC1FACE83AC5 + +Count = 602 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D5691FFB38F7E92CDA + +Count = 603 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D5E58A32D05C36AE50 + +Count = 604 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52D54ABD1D01AD2F8 + +Count = 605 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D5A65779621209420B + +Count = 606 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D5E06EE45EFFFE4868 + +Count = 607 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D5BA8C6D6E659F242E + +Count = 608 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D545986F937FCD11FA + +Count = 609 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D502ECAA93096E40BD + +Count = 610 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D5B3B65BBB32E2B9E9 + +Count = 611 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D573640137A8570014 + +Count = 612 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D524B8C248F3DEED23 + +Count = 613 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D5E6103758FA4236BF + +Count = 614 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D517521A596109CAED + +Count = 615 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D5C49FA4C9340F56BE + +Count = 616 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D56436340A0CB706F7 + +Count = 617 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D5D49C832D659CDBBF + +Count = 618 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D5FE73A757EC28D97C + +Count = 619 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52319024D40E2A759 + +Count = 620 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D5DE7FA5656FBC1B70 + +Count = 621 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D50721FD7DA571188F + +Count = 622 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D5B7AC90F4466142E8 + +Count = 623 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D50534DFED96C993CC + +Count = 624 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D5DC7DBCA293FCC411 + +Count = 625 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D51A0AF684E504B814 + +Count = 626 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D5EF5DB125CD2F6F4B + +Count = 627 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D5287CABD4EF5D2CA8 + +Count = 628 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = +CT = FEC941470CB859D735255B80663E807A63D52AF436ED08F7854A6A + +Count = 629 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A5B33C4B48A2548C7 + +Count = 630 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A742A07BACA69B346 + +Count = 631 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A7B4DDE1AFD3C649D + +Count = 632 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52AD602938C1B5222DF + +Count = 633 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A18A72C144F25978D + +Count = 634 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A512BD3C0B78EF324 + +Count = 635 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52AF02AD4E7EC8FE53B + +Count = 636 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A7CBF1D0F475067B1 + +Count = 637 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52AB461840ECB7C1B19 + +Count = 638 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A3F6256BD096F8BEA + +Count = 639 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A795BCB81E4988189 + +Count = 640 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A23B942B17EF9EDCF + +Count = 641 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52ADCAD404C64ABD81B + +Count = 642 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A9BD9854C1208895C + +Count = 643 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A2A83746429847008 + +Count = 644 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52AEA512EE8B331C9F5 + +Count = 645 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52ABD8DED97E8B824C2 + +Count = 646 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A7F251887E124FF5E + +Count = 647 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A8E6735867A6F030C + +Count = 648 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A5DAA8B162F699F5F + +Count = 649 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52AFD031BD517D1CF16 + +Count = 650 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A4DA9ACF27EFA125E + +Count = 651 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A67468888F74E109D + +Count = 652 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52ABA2C2D925B846EB8 + +Count = 653 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A474A8ABA74DAD291 + +Count = 654 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A9E14D2A2BE17D16E + +Count = 655 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A2E99BF2B5D078B09 + +Count = 656 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A9C01F0328DAF5A2D + +Count = 657 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A4548937D889A0DF0 + +Count = 658 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A833FD95BFE6271F5 + +Count = 659 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A76689EFAD649A6AA + +Count = 660 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52AB149840BF43BE549 + +Count = 661 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71528442BF6E4962EA + +Count = 662 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71FD816B0313E96047 + +Count = 663 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71D298A80D53A59BC6 + +Count = 664 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71DDFF71AD64F04C1D + +Count = 665 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A7170B03C3B829E0A5F + +Count = 666 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71BE1583A3D6E9BF0D + +Count = 667 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71F7997C772E42DBA4 + +Count = 668 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A7156987B507543CDBB + +Count = 669 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71DA0DB2B8DE9C4F31 + +Count = 670 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A7112D32BB952B03399 + +Count = 671 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A7199D0F90A90A3A36A + +Count = 672 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71DFE964367D54A909 + +Count = 673 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71850BED06E735C54F + +Count = 674 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A717A1FEFFBFD67F09B + +Count = 675 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A713D6B2AFB8BC4A1DC + +Count = 676 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A718C31DBD3B0485888 + +Count = 677 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A714CE3815F2AFDE175 + +Count = 678 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A711B3F422071740C42 + +Count = 679 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71D997B73078E8D7DE + +Count = 680 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A7128D59A31E3A32B8C + +Count = 681 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71FB1824A1B6A5B7DF + +Count = 682 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A715BB1B4628E1DE796 + +Count = 683 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71EB1B0345E7363ADE + +Count = 684 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71C1F4273F6E82381D + +Count = 685 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A711C9E8225C2484638 + +Count = 686 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71E1F8250DED16FA11 + +Count = 687 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A7138A67D1527DBF9EE + +Count = 688 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71882B109CC4CBA389 + +Count = 689 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A713AB35F85146372AD + +Count = 690 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71E3FA3CCA11562570 + +Count = 691 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71258D76EC67AE5975 + +Count = 692 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71D0DA314D4F858E2A + +Count = 693 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A7117FB2BBC6DF7CDC9 + +Count = 694 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A7182F7CF78EF4708A1F1 + +Count = 695 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A718258CA51533AA8A35C + +Count = 696 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A718277D3925D7AE458DD + +Count = 697 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A718278B44BFD4DB18F06 + +Count = 698 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A7182D5FB066BABDFC944 + +Count = 699 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71821B5EB9F3FFA87C16 + +Count = 700 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A718252D24627070318BF + +Count = 701 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A7182F3D341005C020EA0 + +Count = 702 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71827F4688E8F7DD8C2A + +Count = 703 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A7182B79811E97BF1F082 + +Count = 704 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71823C9BC35AB9E26071 + +Count = 705 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71827AA25E6654156A12 + +Count = 706 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71822040D756CE740654 + +Count = 707 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A7182DF54D5ABD4263380 + +Count = 708 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A7182982010ABA28562C7 + +Count = 709 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A7182297AE18399099B93 + +Count = 710 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A7182E9A8BB0F03BC226E + +Count = 711 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A7182BE7478705835CF59 + +Count = 712 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71827CDC8D6051A914C5 + +Count = 713 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71828D9EA061CAE2E897 + +Count = 714 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71825E531EF19FE474C4 + +Count = 715 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A7182FEFA8E32A75C248D + +Count = 716 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71824E503915CE77F9C5 + +Count = 717 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A718264BF1D6F47C3FB06 + +Count = 718 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A7182B9D5B875EB098523 + +Count = 719 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A718244B31F5DC457390A + +Count = 720 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829DED47450E9A3AF5 + +Count = 721 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71822D602ACCED8A6092 + +Count = 722 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829FF865D53D22B1B6 + +Count = 723 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A718246B1069A3817E66B + +Count = 724 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A718280C64CBC4EEF9A6E + +Count = 725 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A718275910B1D66C44D31 + +Count = 726 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A7182B2B011EC44B60ED2 + +Count = 727 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F40136AEEE40417C1 + +Count = 728 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829FEF16435299A4156C + +Count = 729 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829FC00F805CD9E8EEED + +Count = 730 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829FCF6859FCEEBD3936 + +Count = 731 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F6227146A08D37F74 + +Count = 732 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829FAC82ABF25CA4CA26 + +Count = 733 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829FE50E5426A40FAE8F + +Count = 734 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F440F5301FF0EB890 + +Count = 735 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829FC89A9AE954D13A1A + +Count = 736 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F004403E8D8FD46B2 + +Count = 737 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F8B47D15B1AEED641 + +Count = 738 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829FCD7E4C67F719DC22 + +Count = 739 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F979CC5576D78B064 + +Count = 740 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F6888C7AA772A85B0 + +Count = 741 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F2FFC02AA0189D4F7 + +Count = 742 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F9EA6F3823A052DA3 + +Count = 743 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F5E74A90EA0B0945E + +Count = 744 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F09A86A71FB397969 + +Count = 745 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829FCB009F61F2A5A2F5 + +Count = 746 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F3A42B26069EE5EA7 + +Count = 747 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829FE98F0CF03CE8C2F4 + +Count = 748 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F49269C33045092BD + +Count = 749 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829FF98C2B146D7B4FF5 + +Count = 750 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829FD3630F6EE4CF4D36 + +Count = 751 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0E09AA7448053313 + +Count = 752 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829FF36F0D5C675B8F3A + +Count = 753 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F2A315544AD968CC5 + +Count = 754 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F9ABC38CD4E86D6A2 + +Count = 755 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F282477D49E2E0786 + +Count = 756 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829FF16D149B9B1B505B + +Count = 757 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F371A5EBDEDE32C5E + +Count = 758 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829FC24D191CC5C8FB01 + +Count = 759 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F056C03EDE7BAB8E2 + +Count = 760 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BE9115FD98DC24AD6 + +Count = 761 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B46147665F062487B + +Count = 762 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B690DB56BB02EB3FA + +Count = 763 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B666A6CCB877B6421 + +Count = 764 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BCB25215D61152263 + +Count = 765 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B05809EC535629731 + +Count = 766 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B4C0C6111CDC9F398 + +Count = 767 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BED0D663696C8E587 + +Count = 768 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6198AFDE3D17670D + +Count = 769 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA94636DFB13B1BA5 + +Count = 770 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B2245E46C73288B56 + +Count = 771 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B647C79509EDF8135 + +Count = 772 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B3E9EF06004BEED73 + +Count = 773 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BC18AF29D1EECD8A7 + +Count = 774 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B86FE379D684F89E0 + +Count = 775 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B37A4C6B553C370B4 + +Count = 776 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF7769C39C976C949 + +Count = 777 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA0AA5F4692FF247E + +Count = 778 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6202AA569B63FFE2 + +Count = 779 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B93408757002803B0 + +Count = 780 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B408D39C7552E9FE3 + +Count = 781 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BE024A9046D96CFAA + +Count = 782 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B508E1E2304BD12E2 + +Count = 783 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B7A613A598D091021 + +Count = 784 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BA70B9F4321C36E04 + +Count = 785 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B5A6D386B0E9DD22D + +Count = 786 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B83336073C450D1D2 + +Count = 787 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B33BE0DFA27408BB5 + +Count = 788 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B812642E3F7E85A91 + +Count = 789 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B586F21ACF2DD0D4C + +Count = 790 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B9E186B8A84257149 + +Count = 791 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0B6B4F2C2BAC0EA616 + +Count = 792 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BAC6E36DA8E7CE5F5 + +Count = 793 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF321133DC6BF15EAF6 + +Count = 794 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF38E16147AC2B5E85B + +Count = 795 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A10FD77482F913DA + +Count = 796 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AE680ED4B5ACC401 + +Count = 797 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF30327434253C28243 + +Count = 798 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3CD82FCDA07B53711 + +Count = 799 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3840E030EFF1E53B8 + +Count = 800 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3250F0429A41F45A7 + +Count = 801 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A99ACDC10FC0C72D + +Count = 802 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3614454C083ECBB85 + +Count = 803 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3EA47867341FF2B76 + +Count = 804 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AC7E1B4FAC082115 + +Count = 805 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3F69C927F36694D53 + +Count = 806 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3098890822C3B7887 + +Count = 807 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF34EFC55825A9829C0 + +Count = 808 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3FFA6A4AA6114D094 + +Count = 809 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF33F74FE26FBA16969 + +Count = 810 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF368A83D59A028845E + +Count = 811 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3AA00C849A9B45FC2 + +Count = 812 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF35B42E54832FFA390 + +Count = 813 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3888F5BD867F93FC3 + +Count = 814 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF32826CB1B5F416F8A + +Count = 815 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3988C7C3C366AB2C2 + +Count = 816 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3B2635846BFDEB001 + +Count = 817 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF36F09FD5C1314CE24 + +Count = 818 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3926F5A743C4A720D + +Count = 819 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF34B31026CF68771F2 + +Count = 820 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3FBBC6FE515972B95 + +Count = 821 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3492420FCC53FFAB1 + +Count = 822 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3906D43B3C00AAD6C + +Count = 823 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3561A0995B6F2D169 + +Count = 824 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3A34D4E349ED90636 + +Count = 825 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF3646C54C5BCAB45D5 + +Count = 826 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C5B28C82D80F3CB89 + +Count = 827 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CF42DE191FD53C924 + +Count = 828 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CDB34229FBD1F32A5 + +Count = 829 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD453FB3F8A4AE57E + +Count = 830 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C791CB6A96C24A33C + +Count = 831 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CB7B909313853166E + +Count = 832 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CFE35F6E5C0F872C7 + +Count = 833 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C5F34F1C29BF964D8 + +Count = 834 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD3A1382A3026E652 + +Count = 835 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1B7FA12BBC0A9AFA + +Count = 836 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C907C73987E190A09 + +Count = 837 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD645EEA493EE006A + +Count = 838 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C8CA76794098F6C2C + +Count = 839 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C73B3656913DD59F8 + +Count = 840 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C34C7A069657E08BF + +Count = 841 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C859D51415EF2F1EB + +Count = 842 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C454F0BCDC4474816 + +Count = 843 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1293C8B29FCEA521 + +Count = 844 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD03B3DA296527EBD + +Count = 845 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C217910A30D1982EF + +Count = 846 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CF2B4AE33581F1EBC + +Count = 847 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C521D3EF060A74EF5 + +Count = 848 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CE2B789D7098C93BD + +Count = 849 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CC858ADAD8038917E + +Count = 850 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C153208B72CF2EF5B + +Count = 851 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CE854AF9F03AC5372 + +Count = 852 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C310AF787C961508D + +Count = 853 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C81879A0E2A710AEA + +Count = 854 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C331FD517FAD9DBCE + +Count = 855 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CEA56B658FFEC8C13 + +Count = 856 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2C21FC7E8914F016 + +Count = 857 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37CD976BBDFA13F2749 + +Count = 858 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C1E57A12E834D64AA + +Count = 859 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27B83F449CB1372B2C + +Count = 860 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27173A6D20CC972981 + +Count = 861 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273823AE2E8CDBD200 + +Count = 862 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273744778EBB8E05DB + +Count = 863 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C279A0B3A185DE04399 + +Count = 864 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2754AE85800997F6CB + +Count = 865 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C271D227A54F13C9262 + +Count = 866 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27BC237D73AA3D847D + +Count = 867 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2730B6B49B01E206F7 + +Count = 868 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F8682D9A8DCE7A5F + +Count = 869 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27736BFF294FDDEAAC + +Count = 870 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2735526215A22AE0CF + +Count = 871 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C276FB0EB25384B8C89 + +Count = 872 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2790A4E9D82219B95D + +Count = 873 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D7D02CD854BAE81A + +Count = 874 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27668ADDF06F36114E + +Count = 875 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27A658877CF583A8B3 + +Count = 876 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F1844403AE0A4584 + +Count = 877 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27332CB113A7969E18 + +Count = 878 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27C26E9C123CDD624A + +Count = 879 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2711A3228269DBFE19 + +Count = 880 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27B10AB2415163AE50 + +Count = 881 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2701A0056638487318 + +Count = 882 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C272B4F211CB1FC71DB + +Count = 883 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27F62584061D360FFE + +Count = 884 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C270B43232E3268B3D7 + +Count = 885 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D21D7B36F8A5B028 + +Count = 886 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27629016BF1BB5EA4F + +Count = 887 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27D00859A6CB1D3B6B + +Count = 888 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C2709413AE9CE286CB6 + +Count = 889 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27CF3670CFB8D010B3 + +Count = 890 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C273A61376E90FBC7EC + +Count = 891 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27FD402D9FB289840F + +Count = 892 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E664EB0E34E4BFDB08 + +Count = 893 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CBEE2788991FD9A5 + +Count = 894 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E4F7E486D9532224 + +Count = 895 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EB903D26EE06F5FF + +Count = 896 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E646DF70B00868B3BD + +Count = 897 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6887ACF285C1F06EF + +Count = 898 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6C1F630FCA4B46246 + +Count = 899 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E660F737DBFFB57459 + +Count = 900 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EC62FE33546AF6D3 + +Count = 901 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E624BC6732D8468A7B + +Count = 902 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6AFBFB5811A551A88 + +Count = 903 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E98628BDF7A210EB + +Count = 904 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6B364A18D6DC37CAD + +Count = 905 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E64C70A37077914979 + +Count = 906 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60B0466700132183E + +Count = 907 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6BA5E97583ABEE16A + +Count = 908 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E67A8CCDD4A00B5897 + +Count = 909 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E62D500EABFB82B5A0 + +Count = 910 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6EFF8FBBBF21E6E3C + +Count = 911 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E61EBAD6BA6955926E + +Count = 912 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CD77682A3C530E3D + +Count = 913 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E66DDEF8E904EB5E74 + +Count = 914 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6DD744FCE6DC0833C + +Count = 915 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6F79B6BB4E47481FF + +Count = 916 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E62AF1CEAE48BEFFDA + +Count = 917 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6D797698667E043F3 + +Count = 918 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60EC9319EAD2D400C + +Count = 919 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6BE445C174E3D1A6B + +Count = 920 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E60CDC130E9E95CB4F + +Count = 921 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6D59570419BA09C92 + +Count = 922 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E613E23A67ED58E097 + +Count = 923 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6E6B57DC6C57337C8 + +Count = 924 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E621946737E701742B + +Count = 925 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC16EAF1576BD8ED2C + +Count = 926 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCB9EFD8EB1678EF81 + +Count = 927 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC96F61BE556341400 + +Count = 928 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9991C2456161C3DB + +Count = 929 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC34DE8FD3870F8599 + +Count = 930 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCFA7B304BD37830CB + +Count = 931 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCB3F7CF9F2BD35462 + +Count = 932 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC12F6C8B870D2427D + +Count = 933 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9E630150DB0DC0F7 + +Count = 934 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC56BD98515721BC5F + +Count = 935 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCDDBE4AE295322CAC + +Count = 936 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9B87D7DE78C526CF + +Count = 937 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCC1655EEEE2A44A89 + +Count = 938 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC3E715C13F8F67F5D + +Count = 939 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC790599138E552E1A + +Count = 940 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCC85F683BB5D9D74E + +Count = 941 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC088D32B72F6C6EB3 + +Count = 942 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC5F51F1C874E58384 + +Count = 943 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC9DF904D87D795818 + +Count = 944 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC6CBB29D9E632A44A + +Count = 945 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBF769749B3343819 + +Count = 946 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC1FDF078A8B8C6850 + +Count = 947 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCAF75B0ADE2A7B518 + +Count = 948 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC859A94D76B13B7DB + +Count = 949 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC58F031CDC7D9C9FE + +Count = 950 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCA59696E5E88775D7 + +Count = 951 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC7CC8CEFD224A7628 + +Count = 952 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCCC45A374C15A2C4F + +Count = 953 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC7EDDEC6D11F2FD6B + +Count = 954 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCA7948F2214C7AAB6 + +Count = 955 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC61E3C504623FD6B3 + +Count = 956 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC94B482A54A1401EC + +Count = 957 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CC539598546866420F + +Count = 958 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC9AB6F46C910247FA + +Count = 959 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC35B3DDD0ECA24557 + +Count = 960 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC1AAA1EDEACEEBED6 + +Count = 961 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC15CDC77E9BBB690D + +Count = 962 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCB8828AE87DD52F4F + +Count = 963 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC7627357029A29A1D + +Count = 964 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC3FABCAA4D109FEB4 + +Count = 965 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC9EAACD838A08E8AB + +Count = 966 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC123F046B21D76A21 + +Count = 967 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCDAE19D6AADFB1689 + +Count = 968 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC51E24FD96FE8867A + +Count = 969 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC17DBD2E5821F8C19 + +Count = 970 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC4D395BD5187EE05F + +Count = 971 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCB22D5928022CD58B + +Count = 972 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF5599C28748F84CC + +Count = 973 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC44036D004F037D98 + +Count = 974 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC84D1378CD5B6C465 + +Count = 975 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCD30DF4F38E3F2952 + +Count = 976 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC11A501E387A3F2CE + +Count = 977 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCE0E72CE21CE80E9C + +Count = 978 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC332A927249EE92CF + +Count = 979 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC938302B17156C286 + +Count = 980 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC2329B596187D1FCE + +Count = 981 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC09C691EC91C91D0D + +Count = 982 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCD4AC34F63D036328 + +Count = 983 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC29CA93DE125DDF01 + +Count = 984 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF094CBC6D890DCFE + +Count = 985 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC4019A64F3B808699 + +Count = 986 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCF281E956EB2857BD + +Count = 987 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC2BC88A19EE1D0060 + +Count = 988 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCEDBFC03F98E57C65 + +Count = 989 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC18E8879EB0CEAB3A + +Count = 990 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBCDFC99D6F92BCE8D9 + +Count = 991 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B40FE4CF065DC957E + +Count = 992 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BEFFB654C187C97D3 + +Count = 993 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC0E2A64258306C52 + +Count = 994 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCF857FE26F65BB89 + +Count = 995 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B62CA3274890BFDCB + +Count = 996 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BAC6F8DECDD7C4899 + +Count = 997 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BE5E3723825D72C30 + +Count = 998 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B44E2751F7ED63A2F + +Count = 999 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC877BCF7D509B8A5 + +Count = 1000 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B00A925F65925C40D + +Count = 1001 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B8BAAF7459B3654FE + +Count = 1002 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCD936A7976C15E9D + +Count = 1003 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9771E349ECA032DB + +Count = 1004 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B6865E1B4F6F2070F + +Count = 1005 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B2F1124B480515648 + +Count = 1006 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9E4BD59CBBDDAF1C + +Count = 1007 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5E998F10216816E1 + +Count = 1008 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B09454C6F7AE1FBD6 + +Count = 1009 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BCBEDB97F737D204A + +Count = 1010 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B3AAF947EE836DC18 + +Count = 1011 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BE9622AEEBD30404B + +Count = 1012 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B49CBBA2D85881002 + +Count = 1013 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF9610D0AECA3CD4A + +Count = 1014 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BD38E29706517CF89 + +Count = 1015 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B0EE48C6AC9DDB1AC + +Count = 1016 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF3822B42E6830D85 + +Count = 1017 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B2ADC735A2C4E0E7A + +Count = 1018 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B9A511ED3CF5E541D + +Count = 1019 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B28C951CA1FF68539 + +Count = 1020 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BF18032851AC3D2E4 + +Count = 1021 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B37F778A36C3BAEE1 + +Count = 1022 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6BC2A03F02441079BE + +Count = 1023 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B058125F366623A5D + +Count = 1024 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AC550DC80ABDC9E65 + +Count = 1025 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A6A55F53CD67C9CC8 + +Count = 1026 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A454C363296306749 + +Count = 1027 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4A2BEF92A165B092 + +Count = 1028 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AE764A204470BF6D0 + +Count = 1029 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A29C11D9C137C4382 + +Count = 1030 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A604DE248EBD7272B + +Count = 1031 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AC14CE56FB0D63134 + +Count = 1032 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4DD92C871B09B3BE + +Count = 1033 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8507B5869725CF16 + +Count = 1034 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A0E04673555365FE5 + +Count = 1035 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A483DFA09B8C15586 + +Count = 1036 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A12DF733922A039C0 + +Count = 1037 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AEDCB71C438F20C14 + +Count = 1038 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAABFB4C44E515D53 + +Count = 1039 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1BE545EC75DDA407 + +Count = 1040 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ADB371F60EF681DFA + +Count = 1041 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8CEBDC1FB4E1F0CD + +Count = 1042 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A4E43290FBD7D2B51 + +Count = 1043 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ABF01040E2636D703 + +Count = 1044 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A6CCCBA9E73304B50 + +Count = 1045 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5ACC652A5D4B881B19 + +Count = 1046 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A7CCF9D7A22A3C651 + +Count = 1047 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A5620B900AB17C492 + +Count = 1048 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A8B4A1C1A07DDBAB7 + +Count = 1049 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A762CBB322883069E + +Count = 1050 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAF72E32AE24E0561 + +Count = 1051 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1FFF8EA3015E5F06 + +Count = 1052 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AAD67C1BAD1F68E22 + +Count = 1053 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A742EA2F5D4C3D9FF + +Count = 1054 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5AB259E8D3A23BA5FA + +Count = 1055 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A470EAF728A1072A5 + +Count = 1056 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A802FB583A8623146 + +Count = 1057 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16129984AAE23DA1FE + +Count = 1058 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16BD9CAD169F9DA353 + +Count = 1059 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1692856E18DFD158D2 + +Count = 1060 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169DE2B7B8E8848F09 + +Count = 1061 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1630ADFA2E0EEAC94B + +Count = 1062 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16FE0845B65A9D7C19 + +Count = 1063 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16B784BA62A23618B0 + +Count = 1064 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A161685BD45F9370EAF + +Count = 1065 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304050607 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169A1074AD52E88C25 + +Count = 1066 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1652CEEDACDEC4F08D + +Count = 1067 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506070809 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16D9CD3F1F1CD7607E + +Count = 1068 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A169FF4A223F1206A1D + +Count = 1069 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16C5162B136B41065B + +Count = 1070 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A163A0229EE7113338F + +Count = 1071 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A167D76ECEE07B062C8 + +Count = 1072 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16CC2C1DC63C3C9B9C + +Count = 1073 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A160CFE474AA6892261 + +Count = 1074 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A165B228435FD00CF56 + +Count = 1075 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16998A7125F49C14CA + +Count = 1076 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1668C85C246FD7E898 + +Count = 1077 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16BB05E2B43AD174CB + +Count = 1078 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A161BAC727702692482 + +Count = 1079 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16AB06C5506B42F9CA + +Count = 1080 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1681E9E12AE2F6FB09 + +Count = 1081 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A165C8344304E3C852C + +Count = 1082 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16A1E5E31861623905 + +Count = 1083 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1678BBBB00ABAF3AFA + +Count = 1084 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16C836D68948BF609D + +Count = 1085 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A167AAE99909817B1B9 + +Count = 1086 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A16A3E7FADF9D22E664 + +Count = 1087 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A166590B0F9EBDA9A61 + +Count = 1088 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1690C7F758C3F14D3E + +Count = 1089 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = FEC941470CB859D735255B80663E807A63D52A71829F0BF37C27E6CCBC6B5A1657E6EDA9E1830EDD + diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.c b/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/api.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.c b/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.c new file mode 100644 index 0000000..770f568 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.c @@ -0,0 +1,881 @@ +/* + * 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 "elephant.h" +#include "internal-keccak.h" +#include "internal-spongent.h" +#include + +aead_cipher_t const dumbo_cipher = { + "Dumbo", + DUMBO_KEY_SIZE, + DUMBO_NONCE_SIZE, + DUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + dumbo_aead_encrypt, + dumbo_aead_decrypt +}; + +aead_cipher_t const jumbo_cipher = { + "Jumbo", + JUMBO_KEY_SIZE, + JUMBO_NONCE_SIZE, + JUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + jumbo_aead_encrypt, + jumbo_aead_decrypt +}; + +aead_cipher_t const delirium_cipher = { + "Delirium", + DELIRIUM_KEY_SIZE, + DELIRIUM_NONCE_SIZE, + DELIRIUM_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + delirium_aead_encrypt, + delirium_aead_decrypt +}; + +/** + * \brief Applies the Dumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void dumbo_lfsr + (unsigned char out[SPONGENT160_STATE_SIZE], + const unsigned char in[SPONGENT160_STATE_SIZE]) +{ + unsigned char temp = + leftRotate3_8(in[0]) ^ (in[3] << 7) ^ (in[13] >> 7); + unsigned index; + for (index = 0; index < SPONGENT160_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT160_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Dumbo. + * + * \param state Points to the Spongent-pi[160] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void dumbo_process_ad + (spongent160_state_t *state, + unsigned char mask[SPONGENT160_STATE_SIZE], + unsigned char next[SPONGENT160_STATE_SIZE], + unsigned char tag[DUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + dumbo_lfsr(next, mask); + dumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state->B, npub, DUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT160_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); + dumbo_lfsr(mask, mask); + dumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT160_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, SPONGENT160_STATE_SIZE); + + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + mlen -= SPONGENT160_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + dumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT160_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + c += temp; + } else if (*clen != DUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DUMBO_TAG_SIZE); + return 0; +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DUMBO_TAG_SIZE) + return -1; + *mlen = clen - DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DUMBO_TAG_SIZE; + while (clen >= SPONGENT160_STATE_SIZE) { + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT160_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + clen -= SPONGENT160_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Jumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void jumbo_lfsr + (unsigned char out[SPONGENT176_STATE_SIZE], + const unsigned char in[SPONGENT176_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ (in[3] << 7) ^ (in[19] >> 7); + unsigned index; + for (index = 0; index < SPONGENT176_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT176_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Jumbo. + * + * \param state Points to the Spongent-pi[170] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void jumbo_process_ad + (spongent176_state_t *state, + unsigned char mask[SPONGENT176_STATE_SIZE], + unsigned char next[SPONGENT176_STATE_SIZE], + unsigned char tag[JUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + jumbo_lfsr(next, mask); + jumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state->B, npub, JUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = JUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT176_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); + jumbo_lfsr(mask, mask); + jumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT176_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, SPONGENT176_STATE_SIZE); + + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + mlen -= SPONGENT176_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + jumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT176_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + c += temp; + } else if (*clen != JUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, JUMBO_TAG_SIZE); + return 0; +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < JUMBO_TAG_SIZE) + return -1; + *mlen = clen - JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= JUMBO_TAG_SIZE; + while (clen >= SPONGENT176_STATE_SIZE) { + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT176_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + clen -= SPONGENT176_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, JUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Delirium LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void delirium_lfsr + (unsigned char out[KECCAKP_200_STATE_SIZE], + const unsigned char in[KECCAKP_200_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ leftRotate1_8(in[2]) ^ (in[13] << 1); + unsigned index; + for (index = 0; index < KECCAKP_200_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[KECCAKP_200_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Delirium. + * + * \param state Points to the Keccak[200] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void delirium_process_ad + (keccakp_200_state_t *state, + unsigned char mask[KECCAKP_200_STATE_SIZE], + unsigned char next[KECCAKP_200_STATE_SIZE], + unsigned char tag[DELIRIUM_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + delirium_lfsr(next, mask); + delirium_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state->B, npub, DELIRIUM_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DELIRIUM_NONCE_SIZE; + while (adlen > 0) { + size = KECCAKP_200_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); + delirium_lfsr(mask, mask); + delirium_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= KECCAKP_200_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, KECCAKP_200_STATE_SIZE); + + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + mlen -= KECCAKP_200_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + delirium_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, KECCAKP_200_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + c += temp; + } else if (*clen != DELIRIUM_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DELIRIUM_TAG_SIZE); + return 0; +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char *mtemp = m; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DELIRIUM_TAG_SIZE) + return -1; + *mlen = clen - DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DELIRIUM_TAG_SIZE; + while (clen >= KECCAKP_200_STATE_SIZE) { + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, KECCAKP_200_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + clen -= KECCAKP_200_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DELIRIUM_TAG_SIZE); +} diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.h new file mode 100644 index 0000000..f775e3d --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/elephant.h @@ -0,0 +1,291 @@ +/* + * 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_ELEPHANT_H +#define LWCRYPTO_ELEPHANT_H + +#include "aead-common.h" + +/** + * \file elephant.h + * \brief Elephant authenticated encryption algorithm family. + * + * Elephant is a family of authenticated encryption algorithms based + * around the Spongent-pi and Keccak permutations. + * + * \li Dumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[160] permutation. This is + * the primary member of the family. + * \li Jumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[176] permutation. + * \li Delirium has a 128-bit key, a 96-bit nonce, and a 128-bit authentication + * tag. It is based around the Keccak[200] permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Dumbo. + */ +#define DUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Dumbo. + */ +#define DUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Dumbo. + */ +#define DUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Jumbo. + */ +#define JUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Jumbo. + */ +#define JUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Jumbo. + */ +#define JUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Delirium. + */ +#define DELIRIUM_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Delirium. + */ +#define DELIRIUM_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Delirium. + */ +#define DELIRIUM_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Dumbo cipher. + */ +extern aead_cipher_t const dumbo_cipher; + +/** + * \brief Meta-information block for the Jumbo cipher. + */ +extern aead_cipher_t const jumbo_cipher; + +/** + * \brief Meta-information block for the Delirium cipher. + */ +extern aead_cipher_t const delirium_cipher; + +/** + * \brief Encrypts and authenticates a packet with Dumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa dumbo_aead_decrypt() + */ +int dumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Dumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa dumbo_aead_encrypt() + */ +int dumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Jumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa jumbo_aead_decrypt() + */ +int jumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Jumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa jumbo_aead_encrypt() + */ +int jumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Delirium. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa delirium_aead_decrypt() + */ +int delirium_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); + +/** + * \brief Decrypts and authenticates a packet with Delirium. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa delirium_aead_encrypt() + */ +int delirium_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/encrypt.c b/elephant/Implementations/crypto_aead/elephant176v1/rhys/encrypt.c new file mode 100644 index 0000000..89b60ae --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "elephant.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 jumbo_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 jumbo_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.c b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.c b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.c new file mode 100644 index 0000000..69a8ecb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.c @@ -0,0 +1,346 @@ +/* + * 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 "internal-spongent.h" + +/** + * \brief Applies the Spongent-pi S-box in parallel to the 8 nibbles + * of a 32-bit word. + * + * \param x3 The input values to the parallel S-boxes. + * + * \return The output values from the parallel S-boxes. + * + * Based on the bit-sliced S-box implementation from here: + * https://github.com/DadaIsCrazy/usuba/blob/master/data/sboxes/spongent.ua + * + * Note that spongent.ua numbers bits from highest to lowest, so x0 is the + * high bit of each nibble and x3 is the low bit. + */ +static uint32_t spongent_sbox(uint32_t x3) +{ + uint32_t q0, q1, q2, q3, t0, t1, t2, t3; + uint32_t x2 = (x3 >> 1); + uint32_t x1 = (x2 >> 1); + uint32_t x0 = (x1 >> 1); + q0 = x0 ^ x2; + q1 = x1 ^ x2; + t0 = q0 & q1; + q2 = ~(x0 ^ x1 ^ x3 ^ t0); + t1 = q2 & ~x0; + q3 = x1 ^ t1; + t2 = q3 & (q3 ^ x2 ^ x3 ^ t0); + t3 = (x2 ^ t0) & ~(x1 ^ t0); + q0 = x1 ^ x2 ^ x3 ^ t2; + q1 = x0 ^ x2 ^ x3 ^ t0 ^ t1; + q2 = x0 ^ x1 ^ x2 ^ t1; + q3 = x0 ^ x3 ^ t0 ^ t3; + return ((q0 << 3) & 0x88888888U) | ((q1 << 2) & 0x44444444U) | + ((q2 << 1) & 0x22222222U) | (q3 & 0x11111111U); +} + +void spongent160_permute(spongent160_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[160] */ + 0x75, 0xae, 0x6a, 0x56, 0x54, 0x2a, 0x29, 0x94, + 0x53, 0xca, 0x27, 0xe4, 0x4f, 0xf2, 0x1f, 0xf8, + 0x3e, 0x7c, 0x7d, 0xbe, 0x7a, 0x5e, 0x74, 0x2e, + 0x68, 0x16, 0x50, 0x0a, 0x21, 0x84, 0x43, 0xc2, + 0x07, 0xe0, 0x0e, 0x70, 0x1c, 0x38, 0x38, 0x1c, + 0x71, 0x8e, 0x62, 0x46, 0x44, 0x22, 0x09, 0x90, + 0x12, 0x48, 0x24, 0x24, 0x49, 0x92, 0x13, 0xc8, + 0x26, 0x64, 0x4d, 0xb2, 0x1b, 0xd8, 0x36, 0x6c, + 0x6d, 0xb6, 0x5a, 0x5a, 0x35, 0xac, 0x6b, 0xd6, + 0x56, 0x6a, 0x2d, 0xb4, 0x5b, 0xda, 0x37, 0xec, + 0x6f, 0xf6, 0x5e, 0x7a, 0x3d, 0xbc, 0x7b, 0xde, + 0x76, 0x6e, 0x6c, 0x36, 0x58, 0x1a, 0x31, 0x8c, + 0x63, 0xc6, 0x46, 0x62, 0x0d, 0xb0, 0x1a, 0x58, + 0x34, 0x2c, 0x69, 0x96, 0x52, 0x4a, 0x25, 0xa4, + 0x4b, 0xd2, 0x17, 0xe8, 0x2e, 0x74, 0x5d, 0xba, + 0x3b, 0xdc, 0x77, 0xee, 0x6e, 0x76, 0x5c, 0x3a, + 0x39, 0x9c, 0x73, 0xce, 0x66, 0x66, 0x4c, 0x32, + 0x19, 0x98, 0x32, 0x4c, 0x65, 0xa6, 0x4a, 0x52, + 0x15, 0xa8, 0x2a, 0x54, 0x55, 0xaa, 0x2b, 0xd4, + 0x57, 0xea, 0x2f, 0xf4, 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4; + uint32_t t0, t1, t2, t3, t4; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); +#endif + + /* Perform the 80 rounds of Spongent-pi[160] */ + for (round = 0; round < 80; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x4 ^= ((uint32_t)(rc[1])) << 24; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + + /* Permute the bits of the state. Bit i is moved to (40 * i) % 159 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + #define BCP(x, bit) ((x) & (((uint32_t)1) << (bit))) + #define BUP(x, from, to) \ + (((x) << ((to) - (from))) & (((uint32_t)1) << (to))) + #define BDN(x, from, to) \ + (((x) >> ((from) - (to))) & (((uint32_t)1) << (to))) + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 8) ^ BUP(t0, 5, 9) ^ BUP(t0, 9, 10) ^ + BDN(t0, 13, 11) ^ BDN(t0, 17, 12) ^ BDN(t0, 21, 13) ^ + BDN(t0, 25, 14) ^ BDN(t0, 29, 15) ^ BUP(t1, 1, 16) ^ + BUP(t1, 5, 17) ^ BUP(t1, 9, 18) ^ BUP(t1, 13, 19) ^ + BUP(t1, 17, 20) ^ BCP(t1, 21) ^ BDN(t1, 25, 22) ^ + BDN(t1, 29, 23) ^ BUP(t2, 1, 24) ^ BUP(t2, 5, 25) ^ + BUP(t2, 9, 26) ^ BUP(t2, 13, 27) ^ BUP(t2, 17, 28) ^ + BUP(t2, 21, 29) ^ BUP(t2, 25, 30) ^ BUP(t2, 29, 31) ^ + BCP(t4, 0) ^ BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ + BDN(t4, 12, 3) ^ BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ + BDN(t4, 24, 6) ^ BDN(t4, 28, 7); + x2 = BUP(t0, 2, 16) ^ BUP(t0, 6, 17) ^ BUP(t0, 10, 18) ^ + BUP(t0, 14, 19) ^ BUP(t0, 18, 20) ^ BDN(t0, 22, 21) ^ + BDN(t0, 26, 22) ^ BDN(t0, 30, 23) ^ BUP(t1, 2, 24) ^ + BUP(t1, 6, 25) ^ BUP(t1, 10, 26) ^ BUP(t1, 14, 27) ^ + BUP(t1, 18, 28) ^ BUP(t1, 22, 29) ^ BUP(t1, 26, 30) ^ + BUP(t1, 30, 31) ^ BDN(t3, 1, 0) ^ BDN(t3, 5, 1) ^ + BDN(t3, 9, 2) ^ BDN(t3, 13, 3) ^ BDN(t3, 17, 4) ^ + BDN(t3, 21, 5) ^ BDN(t3, 25, 6) ^ BDN(t3, 29, 7) ^ + BUP(t4, 1, 8) ^ BUP(t4, 5, 9) ^ BUP(t4, 9, 10) ^ + BDN(t4, 13, 11) ^ BDN(t4, 17, 12) ^ BDN(t4, 21, 13) ^ + BDN(t4, 25, 14) ^ BDN(t4, 29, 15); + x3 = BUP(t0, 3, 24) ^ BUP(t0, 7, 25) ^ BUP(t0, 11, 26) ^ + BUP(t0, 15, 27) ^ BUP(t0, 19, 28) ^ BUP(t0, 23, 29) ^ + BUP(t0, 27, 30) ^ BCP(t0, 31) ^ BDN(t2, 2, 0) ^ + BDN(t2, 6, 1) ^ BDN(t2, 10, 2) ^ BDN(t2, 14, 3) ^ + BDN(t2, 18, 4) ^ BDN(t2, 22, 5) ^ BDN(t2, 26, 6) ^ + BDN(t2, 30, 7) ^ BUP(t3, 2, 8) ^ BUP(t3, 6, 9) ^ + BCP(t3, 10) ^ BDN(t3, 14, 11) ^ BDN(t3, 18, 12) ^ + BDN(t3, 22, 13) ^ BDN(t3, 26, 14) ^ BDN(t3, 30, 15) ^ + BUP(t4, 2, 16) ^ BUP(t4, 6, 17) ^ BUP(t4, 10, 18) ^ + BUP(t4, 14, 19) ^ BUP(t4, 18, 20) ^ BDN(t4, 22, 21) ^ + BDN(t4, 26, 22) ^ BDN(t4, 30, 23); + x4 = BDN(t1, 3, 0) ^ BDN(t1, 7, 1) ^ BDN(t1, 11, 2) ^ + BDN(t1, 15, 3) ^ BDN(t1, 19, 4) ^ BDN(t1, 23, 5) ^ + BDN(t1, 27, 6) ^ BDN(t1, 31, 7) ^ BUP(t2, 3, 8) ^ + BUP(t2, 7, 9) ^ BDN(t2, 11, 10) ^ BDN(t2, 15, 11) ^ + BDN(t2, 19, 12) ^ BDN(t2, 23, 13) ^ BDN(t2, 27, 14) ^ + BDN(t2, 31, 15) ^ BUP(t3, 3, 16) ^ BUP(t3, 7, 17) ^ + BUP(t3, 11, 18) ^ BUP(t3, 15, 19) ^ BUP(t3, 19, 20) ^ + BDN(t3, 23, 21) ^ BDN(t3, 27, 22) ^ BDN(t3, 31, 23) ^ + BUP(t4, 3, 24) ^ BUP(t4, 7, 25) ^ BUP(t4, 11, 26) ^ + BUP(t4, 15, 27) ^ BUP(t4, 19, 28) ^ BUP(t4, 23, 29) ^ + BUP(t4, 27, 30) ^ BCP(t4, 31); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); +#endif +} + +void spongent176_permute(spongent176_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[176] */ + 0x45, 0xa2, 0x0b, 0xd0, 0x16, 0x68, 0x2c, 0x34, + 0x59, 0x9a, 0x33, 0xcc, 0x67, 0xe6, 0x4e, 0x72, + 0x1d, 0xb8, 0x3a, 0x5c, 0x75, 0xae, 0x6a, 0x56, + 0x54, 0x2a, 0x29, 0x94, 0x53, 0xca, 0x27, 0xe4, + 0x4f, 0xf2, 0x1f, 0xf8, 0x3e, 0x7c, 0x7d, 0xbe, + 0x7a, 0x5e, 0x74, 0x2e, 0x68, 0x16, 0x50, 0x0a, + 0x21, 0x84, 0x43, 0xc2, 0x07, 0xe0, 0x0e, 0x70, + 0x1c, 0x38, 0x38, 0x1c, 0x71, 0x8e, 0x62, 0x46, + 0x44, 0x22, 0x09, 0x90, 0x12, 0x48, 0x24, 0x24, + 0x49, 0x92, 0x13, 0xc8, 0x26, 0x64, 0x4d, 0xb2, + 0x1b, 0xd8, 0x36, 0x6c, 0x6d, 0xb6, 0x5a, 0x5a, + 0x35, 0xac, 0x6b, 0xd6, 0x56, 0x6a, 0x2d, 0xb4, + 0x5b, 0xda, 0x37, 0xec, 0x6f, 0xf6, 0x5e, 0x7a, + 0x3d, 0xbc, 0x7b, 0xde, 0x76, 0x6e, 0x6c, 0x36, + 0x58, 0x1a, 0x31, 0x8c, 0x63, 0xc6, 0x46, 0x62, + 0x0d, 0xb0, 0x1a, 0x58, 0x34, 0x2c, 0x69, 0x96, + 0x52, 0x4a, 0x25, 0xa4, 0x4b, 0xd2, 0x17, 0xe8, + 0x2e, 0x74, 0x5d, 0xba, 0x3b, 0xdc, 0x77, 0xee, + 0x6e, 0x76, 0x5c, 0x3a, 0x39, 0x9c, 0x73, 0xce, + 0x66, 0x66, 0x4c, 0x32, 0x19, 0x98, 0x32, 0x4c, + 0x65, 0xa6, 0x4a, 0x52, 0x15, 0xa8, 0x2a, 0x54, + 0x55, 0xaa, 0x2b, 0xd4, 0x57, 0xea, 0x2f, 0xf4, + 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t t0, t1, t2, t3, t4, t5; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; + x5 = state->W[5]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); + x5 = le_load_word16(state->B + 20); /* Last word is only 16 bits */ +#endif + + /* Perform the 90 rounds of Spongent-pi[176] */ + for (round = 0; round < 90; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x5 ^= ((uint32_t)(rc[1])) << 8; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + t5 = spongent_sbox(x5); + + /* Permute the bits of the state. Bit i is moved to (44 * i) % 175 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 12) ^ BUP(t0, 5, 13) ^ BUP(t0, 9, 14) ^ + BUP(t0, 13, 15) ^ BDN(t0, 17, 16) ^ BDN(t0, 21, 17) ^ + BDN(t0, 25, 18) ^ BDN(t0, 29, 19) ^ BUP(t1, 1, 20) ^ + BUP(t1, 5, 21) ^ BUP(t1, 9, 22) ^ BUP(t1, 13, 23) ^ + BUP(t1, 17, 24) ^ BUP(t1, 21, 25) ^ BUP(t1, 25, 26) ^ + BDN(t1, 29, 27) ^ BUP(t2, 1, 28) ^ BUP(t2, 5, 29) ^ + BUP(t2, 9, 30) ^ BUP(t2, 13, 31) ^ BCP(t4, 0) ^ + BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ BDN(t4, 12, 3) ^ + BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ BDN(t4, 24, 6) ^ + BDN(t4, 28, 7) ^ BUP(t5, 0, 8) ^ BUP(t5, 4, 9) ^ + BUP(t5, 8, 10) ^ BDN(t5, 12, 11); + x2 = BUP(t0, 2, 24) ^ BUP(t0, 6, 25) ^ BUP(t0, 10, 26) ^ + BUP(t0, 14, 27) ^ BUP(t0, 18, 28) ^ BUP(t0, 22, 29) ^ + BUP(t0, 26, 30) ^ BUP(t0, 30, 31) ^ BDN(t2, 17, 0) ^ + BDN(t2, 21, 1) ^ BDN(t2, 25, 2) ^ BDN(t2, 29, 3) ^ + BUP(t3, 1, 4) ^ BCP(t3, 5) ^ BDN(t3, 9, 6) ^ + BDN(t3, 13, 7) ^ BDN(t3, 17, 8) ^ BDN(t3, 21, 9) ^ + BDN(t3, 25, 10) ^ BDN(t3, 29, 11) ^ BUP(t4, 1, 12) ^ + BUP(t4, 5, 13) ^ BUP(t4, 9, 14) ^ BUP(t4, 13, 15) ^ + BDN(t4, 17, 16) ^ BDN(t4, 21, 17) ^ BDN(t4, 25, 18) ^ + BDN(t4, 29, 19) ^ BUP(t5, 1, 20) ^ BUP(t5, 5, 21) ^ + BUP(t5, 9, 22) ^ BUP(t5, 13, 23); + x3 = BDN(t1, 2, 0) ^ BDN(t1, 6, 1) ^ BDN(t1, 10, 2) ^ + BDN(t1, 14, 3) ^ BDN(t1, 18, 4) ^ BDN(t1, 22, 5) ^ + BDN(t1, 26, 6) ^ BDN(t1, 30, 7) ^ BUP(t2, 2, 8) ^ + BUP(t2, 6, 9) ^ BCP(t2, 10) ^ BDN(t2, 14, 11) ^ + BDN(t2, 18, 12) ^ BDN(t2, 22, 13) ^ BDN(t2, 26, 14) ^ + BDN(t2, 30, 15) ^ BUP(t3, 2, 16) ^ BUP(t3, 6, 17) ^ + BUP(t3, 10, 18) ^ BUP(t3, 14, 19) ^ BUP(t3, 18, 20) ^ + BDN(t3, 22, 21) ^ BDN(t3, 26, 22) ^ BDN(t3, 30, 23) ^ + BUP(t4, 2, 24) ^ BUP(t4, 6, 25) ^ BUP(t4, 10, 26) ^ + BUP(t4, 14, 27) ^ BUP(t4, 18, 28) ^ BUP(t4, 22, 29) ^ + BUP(t4, 26, 30) ^ BUP(t4, 30, 31); + x4 = BUP(t0, 3, 4) ^ BDN(t0, 7, 5) ^ BDN(t0, 11, 6) ^ + BDN(t0, 15, 7) ^ BDN(t0, 19, 8) ^ BDN(t0, 23, 9) ^ + BDN(t0, 27, 10) ^ BDN(t0, 31, 11) ^ BUP(t1, 3, 12) ^ + BUP(t1, 7, 13) ^ BUP(t1, 11, 14) ^ BCP(t1, 15) ^ + BDN(t1, 19, 16) ^ BDN(t1, 23, 17) ^ BDN(t1, 27, 18) ^ + BDN(t1, 31, 19) ^ BUP(t2, 3, 20) ^ BUP(t2, 7, 21) ^ + BUP(t2, 11, 22) ^ BUP(t2, 15, 23) ^ BUP(t2, 19, 24) ^ + BUP(t2, 23, 25) ^ BDN(t2, 27, 26) ^ BDN(t2, 31, 27) ^ + BUP(t3, 3, 28) ^ BUP(t3, 7, 29) ^ BUP(t3, 11, 30) ^ + BUP(t3, 15, 31) ^ BDN(t5, 2, 0) ^ BDN(t5, 6, 1) ^ + BDN(t5, 10, 2) ^ BDN(t5, 14, 3); + x5 = BDN(t3, 19, 0) ^ BDN(t3, 23, 1) ^ BDN(t3, 27, 2) ^ + BDN(t3, 31, 3) ^ BUP(t4, 3, 4) ^ BDN(t4, 7, 5) ^ + BDN(t4, 11, 6) ^ BDN(t4, 15, 7) ^ BDN(t4, 19, 8) ^ + BDN(t4, 23, 9) ^ BDN(t4, 27, 10) ^ BDN(t4, 31, 11) ^ + BUP(t5, 3, 12) ^ BUP(t5, 7, 13) ^ BUP(t5, 11, 14) ^ + BCP(t5, 15); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; + state->W[5] = x5; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); + le_store_word16(state->B + 20, x5); /* Last word is only 16 bits */ +#endif +} diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.h new file mode 100644 index 0000000..bb9823f --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-spongent.h @@ -0,0 +1,91 @@ +/* + * 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_SPONGENT_H +#define LW_INTERNAL_SPONGENT_H + +#include "internal-util.h" + +/** + * \file internal-spongent.h + * \brief Internal implementation of the Spongent-pi permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the Spongent-pi[160] state in bytes. + */ +#define SPONGENT160_STATE_SIZE 20 + +/** + * \brief Size of the Spongent-pi[176] state in bytes. + */ +#define SPONGENT176_STATE_SIZE 22 + +/** + * \brief Structure of the internal state of the Spongent-pi[160] permutation. + */ +typedef union +{ + uint32_t W[5]; /**< Spongent-pi[160] state as 32-bit words */ + uint8_t B[20]; /**< Spongent-pi[160] state as bytes */ + +} spongent160_state_t; + +/** + * \brief Structure of the internal state of the Spongent-pi[176] permutation. + * + * Note: The state is technically only 176 bits, but we increase it to + * 192 bits so that we can use 32-bit word operations to manipulate the + * state. The extra bits in the last word are fixed to zero. + */ +typedef union +{ + uint32_t W[6]; /**< Spongent-pi[176] state as 32-bit words */ + uint8_t B[24]; /**< Spongent-pi[176] state as bytes */ + +} spongent176_state_t; + +/** + * \brief Permutes the Spongent-pi[160] state. + * + * \param state The Spongent-pi[160] state to be permuted. + */ +void spongent160_permute(spongent160_state_t *state); + +/** + * \brief Permutes the Spongent-pi[176] state. + * + * \param state The Spongent-pi[176] state to be permuted. + */ +void spongent176_permute(spongent176_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-util.h b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant176v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant200v1/LWC_AEAD_KAT_128_96.txt b/elephant/Implementations/crypto_aead/elephant200v1/LWC_AEAD_KAT_128_96.txt index d17b858..1b18aca 100644 --- a/elephant/Implementations/crypto_aead/elephant200v1/LWC_AEAD_KAT_128_96.txt +++ b/elephant/Implementations/crypto_aead/elephant200v1/LWC_AEAD_KAT_128_96.txt @@ -1,7623 +1,7623 @@ -Count = 1 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = -CT = F15ACBDAAD35B3172B71A67F6D61743E - -Count = 2 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00 -CT = 34A51A359BB2BC6E0FD2FE971A8F2E9A - -Count = 3 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001 -CT = F1B7119EE3E759F50B23D20CC34F3BD2 - -Count = 4 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102 -CT = 68668A3627C7D4FCE5DB770CFDE3B4C6 - -Count = 5 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203 -CT = 65B32A1FF4548BD6C3E880D1F8D29832 - -Count = 6 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304 -CT = 89AEEE9C5A7E3377C3EF1623AC8C18BE - -Count = 7 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405 -CT = F06E6E2DCCAC2B1BE87AA1694A954B85 - -Count = 8 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506 -CT = 7CDE5DB1EACAAE1AED428BB7DA7346A2 - -Count = 9 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 0001020304050607 -CT = 3EF470DA12441DE00B4AF48B299DB5EF - -Count = 10 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708 -CT = 6687F92C696A4E9DA87EA41DAA51081D - -Count = 11 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 00010203040506070809 -CT = CAE0E7766CAEB7E14A8238415E21C48B - -Count = 12 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A -CT = F86A1C0AD98EADBDCA619A3419A6F380 - -Count = 13 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B -CT = 1A27A16634EA15F59B8FBB62CB06BDBC - -Count = 14 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C -CT = B7297B7DB06F6F4DDE9AE6AC0C8302E5 - -Count = 15 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D -CT = B25A050247EE077E52117FEEA4B955E3 - -Count = 16 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E -CT = 360B5CB0CCC1914211DFD65EF1B1F3EF - -Count = 17 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F -CT = F8D62F1384C3258A6E3483766F70B9C3 - -Count = 18 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 2359560C641B5CDACDED28D9C0A45D81 - -Count = 19 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = EBBA4DE56CE76EA0F20B9D6199580005 - -Count = 20 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 1801ADDB77E9E798539E8FB1A490FFA5 - -Count = 21 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 49813ED636C0C4E8741F443FCCD307CC - -Count = 22 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 1BB1ED7F0316E62419057968808702C9 - -Count = 23 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 1E7F9010BDDD33A3CAE79E98C5A4334A - -Count = 24 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 3689CC310FEF5C2ACDA4E1E44C2671D5 - -Count = 25 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 5423B3217C804E5539A1B1FD84FE52BB - -Count = 26 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 1CAEB31F7DE27243E3C99374C555631F - -Count = 27 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = D38C9AD6399301C284F71AA7C4717C80 - -Count = 28 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = A2740607BD980E459E521974E8993835 - -Count = 29 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 9B3760AC69587B865CE014ED915CAB1B - -Count = 30 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = ABE9B4A89C7036B3E64BD759ECEC52A2 - -Count = 31 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = F3921ACC6526F09CE880E05B1C3D5F1D - -Count = 32 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = C56C67DBE9684B200DC84DEE046022BC - -Count = 33 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 5AAE347244FA223539C5F9379B16775D - -Count = 34 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = -CT = 75F797289653F5E1F298E281E32386CFCC - -Count = 35 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00 -CT = 753268F9796572EE8BBC41D90B54689568 - -Count = 36 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001 -CT = 75F77AF2D21D270B10B8B0F5908DA88020 - -Count = 37 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102 -CT = 756EAB697AD907861956485090B3040F34 - -Count = 38 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203 -CT = 75637EC9530A94D933707BA74DB63523C0 - -Count = 39 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304 -CT = 758F630DD0A4BE6192707C31BFE26BA34C - -Count = 40 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405 -CT = 75F6A38D61326C79FE5BE986F50472F077 - -Count = 41 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506 -CT = 757A13BEFD140AFCFF5ED1AC2B9494FD50 - -Count = 42 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 0001020304050607 -CT = 7538399396EC844F05B8D9D317677A0E1D - -Count = 43 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708 -CT = 75604A1A6097AA1C781BED8381E4B6B3EF - -Count = 44 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 00010203040506070809 -CT = 75CC2D043A926EE504F9111FDD10C67F79 - -Count = 45 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A -CT = 75FEA7FF46274EFF5879F2BDA857414872 - -Count = 46 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B -CT = 751CEA422ACA2A4710281C9CFE85E1064E - -Count = 47 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C -CT = 75B1E498314EAF3DA86D09C1304264B917 - -Count = 48 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D -CT = 75B497E64EB92E559BE1825872EA5EEE11 - -Count = 49 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E -CT = 7530C6BFFC3201C3A7A24CF1C2BF56481D - -Count = 50 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75FE1BCC5F7A03776FDDA7A4EA21970231 - -Count = 51 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 752594B5409ADB0E3F7E7E0F458E43E673 - -Count = 52 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75ED77AEA992273C454198BAFDD7BFBBF7 - -Count = 53 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 751ECC4E978929B57DE00DA82DEA774457 - -Count = 54 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 754F4CDD9AC800960DC78C63A38234BC3E - -Count = 55 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 751D7C0E33FDD6B4C1AA965EF4CE60B93B - -Count = 56 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 7518B2735C431D61467974B9048B4388B8 - -Count = 57 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 7530442F7DF12F0ECF7E37C67802C1CA27 - -Count = 58 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 7552EE506D82401CB08A329661CA19E949 - -Count = 59 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 751A635053832220A6505AB4E88BB2D8ED - -Count = 60 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75D541799AC753532737643D3B8A96C772 - -Count = 61 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75A4B9E54B43585CA02DC13EE8A67E83C7 - -Count = 62 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 759DFA83E097982963EF733371DFBB10E9 - -Count = 63 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75AD2457E462B0645655D8F0C5A20BE950 - -Count = 64 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F55FF9809BE6A2795B13C7C752DAE4EF - -Count = 65 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75C3A1849717A819C5BE5B6A724A87994E - -Count = 66 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 755C63D73EBA3A70D08A56DEABD5F1CCAF - -Count = 67 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = -CT = 75F8800643012C02E88E68F12495367A7CBF - -Count = 68 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00 -CT = 75F845F992EE1A85E7F74C527C7D4194261B - -Count = 69 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001 -CT = 75F880EB994562D0026C48A350E698543353 - -Count = 70 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102 -CT = 75F8193A02EDA6F08F65A65BF5E6A6F8BC47 - -Count = 71 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203 -CT = 75F814EFA2C47563D04F8068023BA3C990B3 - -Count = 72 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304 -CT = 75F8F8F26647DB4968EE806F94C9F797103F - -Count = 73 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405 -CT = 75F88132E6F64D9B7082ABFA2383118E4304 - -Count = 74 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506 -CT = 75F80D82D56A6BFDF583AEC2095D81684E23 - -Count = 75 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 0001020304050607 -CT = 75F84FA8F8019373467948CA76617286BD6E - -Count = 76 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708 -CT = 75F817DB71F7E85D1504EBFE26F7F14A009C - -Count = 77 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 00010203040506070809 -CT = 75F8BBBC6FADED99EC780902BAAB053ACC0A - -Count = 78 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A -CT = 75F8893694D158B9F62489E118DE42BDFB01 - -Count = 79 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B -CT = 75F86B7B29BDB5DD4E6CD80F3988901DB53D - -Count = 80 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C -CT = 75F8C675F3A6315834D49D1A644657980A64 - -Count = 81 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D -CT = 75F8C3068DD9C6D95CE71191FD04FFA25D62 - -Count = 82 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E -CT = 75F84757D46B4DF6CADB525F54B4AAAAFB6E - -Count = 83 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8898AA7C805F47E132DB4019C346BB142 - -Count = 84 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F85205DED7E52C07438E6DAA339BBF5500 - -Count = 85 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F89AE6C53EEDD03539B18B1F8BC2430884 - -Count = 86 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8695D2500F6DEBC01101E0D5BFF8BF724 - -Count = 87 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F838DDB60DB7F79F71379FC6D597C80F4D - -Count = 88 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F86AED65A48221BDBD5A85FB82DB9C0A48 - -Count = 89 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F86F2318CB3CEA683A89671C729EBF3BCB - -Count = 90 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F847D544EA8ED807B38E24630E173D7954 - -Count = 91 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8257F3BFAFDB715CC7A213317DFE55A3A - -Count = 92 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F86DF23BC4FCD529DAA049119E9E4E6B9E - -Count = 93 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8A2D0120DB8A45A5BC777984D9F6A7401 - -Count = 94 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8D3288EDC3CAF55DCDDD29B9EB38230B4 - -Count = 95 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8EA6BE877E86F201F1F609607CA47A39A - -Count = 96 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8DAB53C731D476D2AA5CB55B3B7F75A23 - -Count = 97 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F882CE9217E411AB05AB0062B14726579C - -Count = 98 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8B430EF00685F10B94E48CF045F7B2A3D - -Count = 99 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F82BF2BCA9C5CD79AC7A457BDDC00D7FDC - -Count = 100 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = -CT = 75F8BD3516DE07D6044CA2EDC2B2770E1DA70A - -Count = 101 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00 -CT = 75F8BDF0E90FE8E08343DBC961EA9F79F3FDAE - -Count = 102 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001 -CT = 75F8BD35FB044398D6A640CD90C604A033E8E6 - -Count = 103 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102 -CT = 75F8BDAC2A9FEB5CF62B49236863049E9F67F2 - -Count = 104 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203 -CT = 75F8BDA1FF3FC28F657463055B94D99BAE4B06 - -Count = 105 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304 -CT = 75F8BD4DE2FB41214FCCC2055C022BCFF0CB8A - -Count = 106 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405 -CT = 75F8BD34227BF0B79DD4AE2EC9B56129E998B1 - -Count = 107 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506 -CT = 75F8BDB892486C91FB51AF2BF19FBFB90F9596 - -Count = 108 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 0001020304050607 -CT = 75F8BDFAB865076975E255CDF9E0834AE166DB - -Count = 109 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708 -CT = 75F8BDA2CBECF1125BB1286ECDB015C92DDB29 - -Count = 110 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 00010203040506070809 -CT = 75F8BD0EACF2AB179F48548C312C493D5D17BF - -Count = 111 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A -CT = 75F8BD3C2609D7A2BF52080CD28E3C7ADA20B4 - -Count = 112 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B -CT = 75F8BDDE6BB4BB4FDBEA405D3CAF6AA87A6E88 - -Count = 113 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C -CT = 75F8BD73656EA0CB5E90F81829F2A46FFFD1D1 - -Count = 114 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD761610DF3CDFF8CB94A26BE6C7C586D7 - -Count = 115 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BDF247496DB7F06EF7D76CC25692CD20DB - -Count = 116 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD3C9A3ACEFFF2DA3FA887977E0C0C6AF7 - -Count = 117 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BDE71543D11F2AA36F0B5E3CD1A3D88EB5 - -Count = 118 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD2FF6583817D6911534B88969FA24D331 - -Count = 119 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BDDC4DB8060CD8182D952D9BB9C7EC2C91 - -Count = 120 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD8DCD2B0B4DF13B5DB2AC5037AFAFD4F8 - -Count = 121 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BDDFFDF8A278271991DFB66D60E3FBD1FD - -Count = 122 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BDDA3385CDC6ECCC160C548A90A6D8E07E - -Count = 123 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BDF2C5D9EC74DEA39F0B17F5EC2F5AA2E1 - -Count = 124 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD906FA6FC07B1B1E0FF12A5F5E782818F - -Count = 125 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BDD8E2A6C206D38DF6257A877CA629B02B - -Count = 126 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD17C08F0B42A2FE7742440EAFA70DAFB4 - -Count = 127 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD663813DAC6A9F1F058E10D7C8BE5EB01 - -Count = 128 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD5F7B7571126984339A5300E5F220782F - -Count = 129 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD6FA5A175E741C90620F8C3518F908196 - -Count = 130 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD37DE0F111E170F292E33F4537F418C29 - -Count = 131 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD012072069259B495CB7B59E6671CF188 - -Count = 132 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD9EE221AF3FCBDD80FF76ED3FF86AA469 - -Count = 133 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = -CT = 75F8BD7F52BDA7B96A4B5D488D71E517A1DC1495 - -Count = 134 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00 -CT = 75F8BD7F974276565CCC5231A9D2BDFFD6324E31 - -Count = 135 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001 -CT = 75F8BD7F52507DFD2499B7AAAD2391640FF25B79 - -Count = 136 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102 -CT = 75F8BD7FCB81E655E0B93AA343DB3464315ED46D - -Count = 137 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203 -CT = 75F8BD7FC654467C332A658965E8C3B9346FF899 - -Count = 138 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304 -CT = 75F8BD7F2A4982FF9D00DD2865EF554B60317815 - -Count = 139 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405 -CT = 75F8BD7F5389024E0BD2C5444E7AE20186282B2E - -Count = 140 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506 -CT = 75F8BD7FDF3931D22DB440454B42C8DF16CE2609 - -Count = 141 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 0001020304050607 -CT = 75F8BD7F9D131CB9D53AF3BFAD4AB7E3E520D544 - -Count = 142 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708 -CT = 75F8BD7FC560954FAE14A0C20E7EE77566EC68B6 - -Count = 143 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 00010203040506070809 -CT = 75F8BD7F69078B15ABD059BEEC827B29929CA420 - -Count = 144 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A -CT = 75F8BD7F5B8D70691EF043E26C61D95CD51B932B - -Count = 145 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B -CT = 75F8BD7FB9C0CD05F394FBAA3D8FF80A07BBDD17 - -Count = 146 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F14CE171E77118112789AA5C4C03E624E - -Count = 147 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F11BD69618090E921F4113C8668043548 - -Count = 148 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F95EC30D30BBF7F1DB7DF95363D0C9344 - -Count = 149 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F5B31437043BDCBD5C834C01EA3CDD968 - -Count = 150 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F80BE3A6FA365B2856BED6BB10C193D2A - -Count = 151 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F485D2186AB9980FF540BDE0955E560AE - -Count = 152 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7FBBE6C1B8B09709C7F59ECCD9682D9F0E - -Count = 153 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7FEA6652B5F1BE2AB7D21F0757006E6767 - -Count = 154 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7FB856811CC468087BBF053A004C3A6262 - -Count = 155 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7FBD98FC737AA3DDFC6CE7DDF0091953E1 - -Count = 156 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F956EA052C891B2756BA4A28C809B117E - -Count = 157 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7FF7C4DF42BBFEA00A9FA1F29548433210 - -Count = 158 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7FBF49DF7CBA9C9C1C45C9D01C09E803B4 - -Count = 159 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F706BF6B5FEEDEF9D22F759CF08CC1C2B - -Count = 160 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F01936A647AE6E01A38525A1C2424589E - -Count = 161 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F38D00CCFAE2695D9FAE057855DE1CBB0 - -Count = 162 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F080ED8CB5B0ED8EC404B943120513209 - -Count = 163 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F507576AFA2581EC34E80A333D0803FB6 - -Count = 164 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F668B0BB82E16A57FABC80E86C8DD4217 - -Count = 165 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7FF94958118384CC6A9FC5BA5F57AB17F6 - -Count = 166 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = -CT = 75F8BD7F4713632EDC7CD5ADE3F56280918D754F0F - -Count = 167 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00 -CT = 75F8BD7F47D69CFF334A52A29AD1C1D879FA9B15AB - -Count = 168 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001 -CT = 75F8BD7F47138EF49832074701D530F4E2235B00E3 - -Count = 169 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102 -CT = 75F8BD7F478A5F6F30F627CA083BC851E21DF78FF7 - -Count = 170 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203 -CT = 75F8BD7F47878ACF1925B495221DFBA63F18C6A303 - -Count = 171 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304 -CT = 75F8BD7F476B970B9A8B9E2D831DFC30CD4C98238F - -Count = 172 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405 -CT = 75F8BD7F4712578B2B1D4C35EF36698787AA8170B4 - -Count = 173 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506 -CT = 75F8BD7F479EE7B8B73B2AB0EE3351AD593A677D93 - -Count = 174 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 0001020304050607 -CT = 75F8BD7F47DCCD95DCC3A40314D559D265C9898EDE - -Count = 175 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708 -CT = 75F8BD7F4784BE1C2AB88A5069766D82F34A45332C - -Count = 176 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 00010203040506070809 -CT = 75F8BD7F4728D90270BD4EA91594911EAFBE35FFBA - -Count = 177 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A -CT = 75F8BD7F471A53F90C086EB3491472BCDAF9B2C8B1 - -Count = 178 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B -CT = 75F8BD7F47F81E4460E50A0B01459C9D8C2B12868D - -Count = 179 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4755109E7B618F71B90089C042EC9739D4 - -Count = 180 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F475063E004960E198A8C02590044AD6ED2 - -Count = 181 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F47D432B9B61D218FB6CFCCF0B011A5C8DE - -Count = 182 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F471AEFCA1555233B7EB027A5988F6482F2 - -Count = 183 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F47C160B30AB5FB422E13FE0E3720B066B0 - -Count = 184 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F470983A8E3BD0770542C18BB8F794C3B34 - -Count = 185 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F47FA3848DDA609F96C8D8DA95F4484C494 - -Count = 186 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F47ABB8DBD0E720DA1CAA0C62D12CC73CFD - -Count = 187 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F47F9880879D2F6F8D0C7165F86609339F8 - -Count = 188 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F47FC4675166C3D2D5714F4B87625B0087B - -Count = 189 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F47D4B02937DE0F42DE13B7C70AAC324AE4 - -Count = 190 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F47B61A5627AD6050A1E7B2971364EA698A - -Count = 191 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F47FE975619AC026CB73DDAB59A2541582E - -Count = 192 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4731B57FD0E8731F365AE43C49246547B1 - -Count = 193 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F47404DE3016C7810B140413F9A088D0304 - -Count = 194 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F47790E85AAB8B8657282F332037148902A - -Count = 195 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4749D051AE4D9028473858F1B70CF86993 - -Count = 196 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4711ABFFCAB4C6EE683693C6B5FC29642C - -Count = 197 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F47275582DD388855D4D3DB6B00E474198D - -Count = 198 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F47B897D174951A3CC1E7D6DFD97B024C6C - -Count = 199 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = -CT = 75F8BD7F4702B4A392153FB14CC7B698E976C1B4204A - -Count = 200 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00 -CT = 75F8BD7F4702715C43FA093643BE923BB19EB65A7AEE - -Count = 201 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001 -CT = 75F8BD7F4702B44E48517163A62596CA9D056F9A6FA6 - -Count = 202 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102 -CT = 75F8BD7F47022D9FD3F9B5432B2C783238055136E0B2 - -Count = 203 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203 -CT = 75F8BD7F4702204A73D066D074065E01CFD85407CC46 - -Count = 204 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304 -CT = 75F8BD7F4702CC57B753C8FACCA75E06592A00594CCA - -Count = 205 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405 -CT = 75F8BD7F4702B59737E25E28D4CB7593EE60E6401FF1 - -Count = 206 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506 -CT = 75F8BD7F47023927047E784E51CA70ABC4BE76A612D6 - -Count = 207 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 0001020304050607 -CT = 75F8BD7F47027B0D291580C0E23096A3BB828548E19B - -Count = 208 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708 -CT = 75F8BD7F4702237EA0E3FBEEB14D3597EB1406845C69 - -Count = 209 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 00010203040506070809 -CT = 75F8BD7F47028F19BEB9FE2A4831D76B7748F2F490FF - -Count = 210 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A -CT = 75F8BD7F4702BD9345C54B0A526D5788D53DB573A7F4 - -Count = 211 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B -CT = 75F8BD7F47025FDEF8A9A66EEA250666F46B67D3E9C8 - -Count = 212 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702F2D022B222EB909D4373A9A5A0565691 - -Count = 213 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702F7A35CCDD56AF8AECFF830E7086C0197 - -Count = 214 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F470273F2057F5E456E928C3699575D64A79B - -Count = 215 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702BD2F76DC1647DA5AF3DDCC7FC3A5EDB7 - -Count = 216 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F470266A00FC3F69FA30A500467D06C7109F5 - -Count = 217 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702AE43142AFE6391706FE2D268358D5471 - -Count = 218 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F47025DF8F414E56D1848CE77C0B80845ABD1 - -Count = 219 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F47020C786719A4443B38E9F60B36600653B8 - -Count = 220 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F47025E48B4B0919219F484EC36612C5256BD - -Count = 221 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F47025B86C9DF2F59CC73570ED1916971673E - -Count = 222 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702737095FE9D6BA3FA504DAEEDE0F325A1 - -Count = 223 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F470211DAEAEEEE04B185A448FEF4282B06CF - -Count = 224 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F47025957EAD0EF668D937E20DC7D6980376B - -Count = 225 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F47029675C319AB17FE12191E55AE68A428F4 - -Count = 226 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702E78D5FC82F1CF19503BB567D444C6C41 - -Count = 227 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702DECE3963FBDC8456C1095BE43D89FF6F - -Count = 228 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EE10ED670EF4C9637BA29850403906D6 - -Count = 229 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702B66B4303F7A20F4C7569AF52B0E80B69 - -Count = 230 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F470280953E147BECB4F0902102E7A8B576C8 - -Count = 231 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F47021F576DBDD67EDDE5A42CB63E37C32329 - -Count = 232 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = -CT = 75F8BD7F4702EA437F55891181F70BDE51D1422E2BA8FE - -Count = 233 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00 -CT = 75F8BD7F4702EA868084662706F872FAF289AA59C5F25A - -Count = 234 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001 -CT = 75F8BD7F4702EA43928FCD5F531DE9FE03A5318005E712 - -Count = 235 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102 -CT = 75F8BD7F4702EADA4314659B7390E010FB0031BEA96806 - -Count = 236 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203 -CT = 75F8BD7F4702EAD796B44C48E0CFCA36C8F7ECBB9844F2 - -Count = 237 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304 -CT = 75F8BD7F4702EA3B8B70CFE6CA776B36CF611EEFC6C47E - -Count = 238 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405 -CT = 75F8BD7F4702EA424BF07E70186F071D5AD65409DF9745 - -Count = 239 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506 -CT = 75F8BD7F4702EACEFBC3E2567EEA061862FC8A99399A62 - -Count = 240 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 0001020304050607 -CT = 75F8BD7F4702EA8CD1EE89AEF059FCFE6A83B66AD7692F - -Count = 241 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708 -CT = 75F8BD7F4702EAD4A2677FD5DE0A815D5ED320E91BD4DD - -Count = 242 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA78C57925D01AF3FDBFA24F7C1D6B184B - -Count = 243 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA4A4F8259653AE9A13F41ED095AEC2F40 - -Count = 244 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EAA8023F35885E51E96EAFCC5F884C617C - -Count = 245 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA050CE52E0CDB2B512BBA91914FC9DE25 - -Count = 246 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA007F9B51FB5A4362A73108D3E7F38923 - -Count = 247 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA842EC2E37075D55EE4FFA163B2FB2F2F - -Count = 248 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA4AF3B140387761969B14F44B2C3A6503 - -Count = 249 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA917CC85FD8AF18C638CD5FE483EE8141 - -Count = 250 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA599FD3B6D0532ABC072BEA5CDA12DCC5 - -Count = 251 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EAAA243388CB5DA384A6BEF88CE7DA2365 - -Count = 252 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EAFBA4A0858A7480F4813F33028F99DB0C - -Count = 253 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EAA994732CBFA2A238EC250E55C3CDDE09 - -Count = 254 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EAAC5A0E43016977BF3FC7E9A586EEEF8A - -Count = 255 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA84AC5262B35B1836388496D90F6CAD15 - -Count = 256 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EAE6062D72C0340A49CC81C6C0C7B48E7B - -Count = 257 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EAAE8B2D4CC156365F16E9E449861FBFDF - -Count = 258 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA61A90485852745DE71D76D9A873BA040 - -Count = 259 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA10519854012C4A596B726E49ABD3E4F5 - -Count = 260 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA2912FEFFD5EC3F9AA9C063D0D21677DB - -Count = 261 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA19CC2AFB20C472AF136BA064AFA68E62 - -Count = 262 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA41B7849FD992B4801DA097665F7783DD - -Count = 263 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA7749F98855DC0F3CF8E83AD3472AFE7C - -Count = 264 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EAE88BAA21F84E6629CCE58E0AD85CAB9D - -Count = 265 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = -CT = 75F8BD7F4702EA536D5F65A0813549A46484341041EB4E4D - -Count = 266 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00 -CT = 75F8BD7F4702EA53A8A0B44FB7B246DD40276CF8360514E9 - -Count = 267 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001 -CT = 75F8BD7F4702EA536DB2BFE4CFE7A34644D64063EFC501A1 - -Count = 268 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102 -CT = 75F8BD7F4702EA53F463244C0BC72E4FAA2EE563D1698EB5 - -Count = 269 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203 -CT = 75F8BD7F4702EA53F9B68465D85471658C1D12BED458A241 - -Count = 270 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304 -CT = 75F8BD7F4702EA5315AB40E6767EC9C48C1A844C800622CD - -Count = 271 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405 -CT = 75F8BD7F4702EA536C6BC057E0ACD1A8A78F3306661F71F6 - -Count = 272 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506 -CT = 75F8BD7F4702EA53E0DBF3CBC6CA54A9A2B719D8F6F97CD1 - -Count = 273 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 0001020304050607 -CT = 75F8BD7F4702EA53A2F1DEA03E44E75344BF66E405178F9C - -Count = 274 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708 -CT = 75F8BD7F4702EA53FA825756456AB42EE78B367286DB326E - -Count = 275 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA5356E5490C40AE4D520577AA2E72ABFEF8 - -Count = 276 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA53646FB270F58E570E8594085B352CC9F3 - -Count = 277 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA5386220F1C18EAEF46D47A290DE78C87CF - -Count = 278 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA532B2CD5079C6F95FE916F74C320093896 - -Count = 279 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA532E5FAB786BEEFDCD1DE4ED8188336F90 - -Count = 280 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA53AA0EF2CAE0C16BF15E2A4431DD3BC99C - -Count = 281 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA5364D38169A8C3DF3921C1111943FA83B0 - -Count = 282 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA53BF5CF876481BA6698218BAB6EC2E67F2 - -Count = 283 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA5377BFE39F40E79413BDFE0F0EB5D23A76 - -Count = 284 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA53840403A15BE91D2B1C6B1DDE881AC5D6 - -Count = 285 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA53D58490AC1AC03E5B3BEAD650E0593DBF - -Count = 286 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA5387B443052F161C9756F0EB07AC0D38BA - -Count = 287 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA53827A3E6A91DDC91085120CF7E92E0939 - -Count = 288 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA53AA8C624B23EFA6998251738B60AC4BA6 - -Count = 289 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA53C8261D5B5080B4E676542392A87468C8 - -Count = 290 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA5380AB1D6551E288F0AC3C011BE9DF596C - -Count = 291 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA534F8934AC1593FB71CB0288C8E8FB46F3 - -Count = 292 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA533E71A87D9198F4F6D1A78B1BC4130246 - -Count = 293 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA530732CED64558813513158682BDD69168 - -Count = 294 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA5337EC1AD2B070CC00A9BE4536C06668D1 - -Count = 295 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA536F97B4B649260A2FA775723430B7656E - -Count = 296 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535969C9A1C568B193423DDF8128EA18CF - -Count = 297 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 0001020304050607 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA53C6AB9A0868FAD88676306B58B79C4D2E - -Count = 298 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = -CT = 75F8BD7F4702EA535ACD2EE4E235206302B93720871498261B - -Count = 299 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00 -CT = 75F8BD7F4702EA535A08D1350D03A76C7B9D94786F63767CBF - -Count = 300 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001 -CT = 75F8BD7F4702EA535ACDC33EA67BF289E0996554F4BAB669F7 - -Count = 301 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102 -CT = 75F8BD7F4702EA535A5412A50EBFD204E9779DF1F4841AE6E3 - -Count = 302 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203 -CT = 75F8BD7F4702EA535A59C705276C415BC351AE0629812BCA17 - -Count = 303 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304 -CT = 75F8BD7F4702EA535AB5DAC1A4C26BE36251A990DBD5754A9B - -Count = 304 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405 -CT = 75F8BD7F4702EA535ACC1A411554B9FB0E7A3C2791336C19A0 - -Count = 305 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A40AA728972DF7E0F7F040D4FA38A1487 - -Count = 306 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A02805FE28A51CDF5990C72735064E7CA - -Count = 307 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A5AF3D614F17F9E883A3822E5D3A85A38 - -Count = 308 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535AF694C84EF4BB67F4D8C4BEB927D896AE - -Count = 309 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535AC41E3332419B7DA858271CCC605FA1A5 - -Count = 310 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A26538E5EACFFC5E009C93D9AB2FFEF99 - -Count = 311 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A8B5D5445287ABF584CDC6054757A50C0 - -Count = 312 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A8E2E2A3ADFFBD76BC057F916DD4007C6 - -Count = 313 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A0A7F738854D44157839950A68848A1CA - -Count = 314 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535AC4A2002B1CD6F59FFC72058E1689EBE6 - -Count = 315 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1F2D7934FC0E8CCF5FABAE21B95D0FA4 - -Count = 316 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535AD7CE62DDF4F2BEB5604D1B99E0A15220 - -Count = 317 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A247582E3EFFC378DC1D80949DD69AD80 - -Count = 318 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A75F511EEAED514FDE659C2C7B52A55E9 - -Count = 319 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A27C5C2479B0336318B43FF90F97E50EC - -Count = 320 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A220BBF2825C8E3B658A11860BC5D616F - -Count = 321 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A0AFDE30997FA8C3F5FE2671C35DF23F0 - -Count = 322 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A68579C19E4959E40ABE73705FD07009E - -Count = 323 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A20DA9C27E5F7A256718F158CBCAC313A - -Count = 324 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535AEFF8B5EEA186D1D716B19C5FBD882EA5 - -Count = 325 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A9E00293F258DDE500C149F8C91606A10 - -Count = 326 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535AA7434F94F14DAB93CEA69215E8A5F93E - -Count = 327 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A979D9B900465E6A6740D51A195150087 - -Count = 328 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535ACFE635F4FD3320897AC666A365C40D38 - -Count = 329 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535AF91848E3717D9B359F8ECB167D997099 - -Count = 330 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A66DA1B4ADCEFF220AB837FCFE2EF2578 - -Count = 331 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = -CT = 75F8BD7F4702EA535A1C305CBEF8FDC04C6B24F5314FEE4BB14E - -Count = 332 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00 -CT = 75F8BD7F4702EA535A1CF5A36F17CB474312005669A799A5EBEA - -Count = 333 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001 -CT = 75F8BD7F4702EA535A1C30B164BCB312A68904A7453C4065FEA2 - -Count = 334 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102 -CT = 75F8BD7F4702EA535A1CA960FF1477322B80EA5FE03C7EC971B6 - -Count = 335 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CA4B55F3DA4A174AACC6C17E17BF85D42 - -Count = 336 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1C48A89BBE0A8BCC0BCC6B81132FA6DDCE - -Count = 337 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1C31681B0F9C59D467E7FE3659C9BF8EF5 - -Count = 338 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CBDD82893BA3F5166E2C61C87595983D2 - -Count = 339 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CFFF205F842B1E29C04CE63BBAAB7709F - -Count = 340 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CA7818C0E399FB1E1A7FA332D297BCD6D - -Count = 341 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1C0BE692543C5B489D4506AF71DD0B01FB - -Count = 342 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1C396C6928897B52C1C5E50D049A8C36F0 - -Count = 343 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CDB21D444641FEA89940B2C52482C78CC - -Count = 344 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1C762F0E5FE09A9031D11E719C8FA9C795 - -Count = 345 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1C735C7020171BF8025D95E8DE27939093 - -Count = 346 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CF70D29929C346E3E1E5B416E729B369F - -Count = 347 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1C39D05A31D436DAF661B01446EC5A7CB3 - -Count = 348 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE25F232E34EEA3A6C269BFE9438E98F1 - -Count = 349 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1C2ABC38C73C1291DCFD8F0A511A72C575 - -Count = 350 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CD907D8F9271C18E45C1A188127BA3AD5 - -Count = 351 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1C88874BF466353B947B9BD30F4FF9C2BC - -Count = 352 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CDAB7985D53E319581681EE5803ADC7B9 - -Count = 353 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CDF79E532ED28CCDFC56309A8468EF63A - -Count = 354 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CF78FB9135F1AA356C22076D4CF0CB4A5 - -Count = 355 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1C9525C6032C75B129362526CD07D497CB - -Count = 356 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CDDA8C63D2D178D3FEC4D0444467FA66F - -Count = 357 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1C128AEFF46966FEBE8B738D97475BB9F0 - -Count = 358 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1C63727325ED6DF13991D68E446BB3FD45 - -Count = 359 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1C5A31158E39AD84FA536483DD12766E6B - -Count = 360 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1C6AEFC18ACC85C9CFE9CF40696FC697D2 - -Count = 361 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1C32946FEE35D30FE0E704776B9F179A6D - -Count = 362 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1C046A12F9B99DB45C024CDADE874AE7CC - -Count = 363 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 00010203040506070809 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1C9BA84150140FDD4936416E07183CB22D - -Count = 364 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = -CT = 75F8BD7F4702EA535A1CE25C0A2BEADD549AF1B448FE28B6A4CC36 - -Count = 365 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00 -CT = 75F8BD7F4702EA535A1CE299F5FA05EBD3958890EBA6C0C14A9692 - -Count = 366 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001 -CT = 75F8BD7F4702EA535A1CE25CE7F1AE93867013941A8A5B188A83DA - -Count = 367 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102 -CT = 75F8BD7F4702EA535A1CE2C5366A0657A6FD1A7AE22F5B26260CCE - -Count = 368 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE2C8E3CA2F8435A2305CD1D8862317203A - -Count = 369 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE224FE0EAC2A1F1A915CD64E747749A0B6 - -Count = 370 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE25D3E8E1DBCCD02FD7743F93E9150F38D - -Count = 371 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE2D18EBD819AAB87FC727BD3E001B6FEAA - -Count = 372 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE293A490EA622534069473ACDCF2580DE7 - -Count = 373 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE2CBD7191C190B677B3747FC4A7194B015 - -Count = 374 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE267B007461CCF9E07D5BB601685E47C83 - -Count = 375 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE2553AFC3AA9EF845B5558C263C2634B88 - -Count = 376 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE2B7774156448B3C1304B6E33510C305B4 - -Count = 377 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE21A799B4DC00E46AB41A3BEFBD746BAED - -Count = 378 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE21F0AE532378F2E98CD2827B97F7CEDEB - -Count = 379 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE29B5BBC80BCA0B8A48EE68E092A744BE7 - -Count = 380 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE25586CF23F4A20C6CF10DDB21B4B501CB - -Count = 381 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE28E09B63C147A753C52D4708E1B61E589 - -Count = 382 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE246EAADD51C8647466D32C536429DB80D - -Count = 383 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE2B5514DEB0788CE7ECCA7D7E67F5547AD - -Count = 384 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE2E4D1DEE646A1ED0EEB261C681716BFC4 - -Count = 385 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE2B6E10D4F7377CFC2863C213F5B42BAC1 - -Count = 386 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE2B32F7020CDBC1A4555DEC6CF1E618B42 - -Count = 387 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE29BD92C017F8E75CC529DB9B397E3C9DD - -Count = 388 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE2F97353110CE167B3A698E9AA5F3BEAB3 - -Count = 389 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE2B1FE532F0D835BA57CF0CB231E90DB17 - -Count = 390 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE27EDC7AE649F228241BCE42F01FB4C488 - -Count = 391 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE20F24E637CDF927A3016B4123335C803D - -Count = 392 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23667809C19395260C3D94CBA4A991313 - -Count = 393 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE206B95498EC111F5579728F0E3729EAAA - -Count = 394 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE25EC2FAFC1547D97A77B9B80CC7F8E715 - -Count = 395 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE2683C87EB990962C692F115B9DFA59AB4 - -Count = 396 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE2F7FED442349B0BD3A6FCA16040D3CF55 - -Count = 397 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = -CT = 75F8BD7F4702EA535A1CE23E2667F4CAD2004ABC625DDA08BF849DA7 - -Count = 398 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00 -CT = 75F8BD7F4702EA535A1CE23EE3982525E48745C546FE82E0C86AC703 - -Count = 399 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E268A2E8E9CD2A05E420FAE7B11AAD24B - -Count = 400 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23EBF5BB52658F22D57ACF70B7B2F065D5F - -Count = 401 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23EB28E150F8B61727D8AC4FCA62A3771AB - -Count = 402 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E5E93D18C254BCADC8AC36A547E69F127 - -Count = 403 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2753513DB399D2B0A156DD1E9870A21C - -Count = 404 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23EABE362A195FF57B1A46EF7C00896AF3B - -Count = 405 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23EE9C94FCA6D71E44B426688FCFB785C76 - -Count = 406 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23EB1BAC63C165FB736E152D86A78B4E184 - -Count = 407 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E1DDDD866139B4E4A03AE44368CC42D12 - -Count = 408 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2F57231AA6BB5416834DE643CB431A19 - -Count = 409 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23ECD1A9E764BDFEC5ED2A3C71519E35425 - -Count = 410 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E6014446DCF5A96E697B69ADBDE66EB7C - -Count = 411 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E65673A1238DBFED51B3D0399765CBC7A - -Count = 412 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23EE13663A0B3F468E958F3AA2923541A76 - -Count = 413 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2FEB1003FBF6DC212718FF01BD95505A - -Count = 414 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23EF464691C1B2EA57184C154AE1241B418 - -Count = 415 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E3C8772F513D2970BBB27E1164BBDE99C - -Count = 416 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23ECF3C92CB08DC1E331AB2F3C67675163C - -Count = 417 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E9EBC01C649F53D433D3338481E36EE55 - -Count = 418 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23ECC8CD26F7C231F8F5029051F5262EB50 - -Count = 419 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23EC942AF00C2E8CA0883CBE2EF1741DAD3 - -Count = 420 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23EE1B4F32170DAA58184889D939EC3984C - -Count = 421 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E831E8C3103B5B7FE708DCD8A561BBB22 - -Count = 422 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23ECB938C0F02D78BE8AAE5EF0317B08A86 - -Count = 423 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E04B1A5C646A6F869CDDB66D016949519 - -Count = 424 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E75493917C2ADF7EED77E65033A7CD1AC - -Count = 425 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E4C0A5FBC166D822D15CC689A43B94282 - -Count = 426 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E7CD48BB8E345CF18AF67AB2E3E09BB3B - -Count = 427 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E24AF25DC1A130937A1AC9C2CCED8B684 - -Count = 428 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E125158CB965DB28B44E43199D685CB25 - -Count = 429 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E8D930B623BCFDB9E70E9854049F39EC4 - -Count = 430 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = -CT = 75F8BD7F4702EA535A1CE23E2DA4710F232426B4955579426D01DD9895 - -Count = 431 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D618EDECC12A1BBEC71DA1A857633C231 - -Count = 432 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2DA49CD5676AF45E77752B361EAFF3D779 - -Count = 433 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D3D4D4ECFAED4D37E9BD3931E915F586D - -Count = 434 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D3098EEE67D478C54BDE064C3946E7499 - -Count = 435 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2DDC852A65D36D34F5BDE7F231C030F415 - -Count = 436 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2DA545AAD445BF2C999672457B2629A72E - -Count = 437 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D29F5994863D9A998934A6FA5B6CFAA09 - -Count = 438 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D6BDFB4239B571A627542109945215944 - -Count = 439 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D33AC3DD5E079491FD676400FC6EDE4B6 - -Count = 440 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D9FCB238FE5BDB063348ADC53329D2820 - -Count = 441 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2DAD41D8F3509DAA3FB4697E26751A1F2B - -Count = 442 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D4F0C659FBDF91277E5875F70A7BA5117 - -Count = 443 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2DE202BF84397C68CFA09202BE603FEE4E - -Count = 444 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2DE771C1FBCEFD00FC2C199BFCC805B948 - -Count = 445 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D6320984945D296C06FD7324C9D0D1F44 - -Count = 446 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2DADFDEBEA0DD02208103C676403CC5568 - -Count = 447 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D767292F5ED085B58B3E5CCCBAC18B12A - -Count = 448 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2DBE91891CE5F469228C037973F5E4ECAE - -Count = 449 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D4D2A6922FEFAE01A2D966BA3C82C130E - -Count = 450 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D1CAAFA2FBFD3C36A0A17A02DA06FEB67 - -Count = 451 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D4E9A29868A05E1A6670D9D7AEC3BEE62 - -Count = 452 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D4B5454E934CE3421B4EF7A8AA918DFE1 - -Count = 453 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D63A208C886FC5BA8B3AC05F6209A9D7E - -Count = 454 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D010877D8F59349D747A955EFE842BE10 - -Count = 455 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D498577E6F4F175C19DC17766A9E98FB4 - -Count = 456 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D86A75E2FB0800640FAFFFEB5A8CD902B - -Count = 457 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2DF75FC2FE348B09C7E05AFD668425D49E - -Count = 458 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2DCE1CA455E04B7C0422E8F0FFFDE047B0 - -Count = 459 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2DFEC27051156331319843334B8050BE09 - -Count = 460 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2DA6B9DE35EC35F71E968804497081B3B6 - -Count = 461 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D9047A322607B4CA273C0A9FC68DCCE17 - -Count = 462 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D0F85F08BCDE925B747CD1D25F7AA9BF6 - -Count = 463 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = -CT = 75F8BD7F4702EA535A1CE23E2D07EFCC1CCFBB3E95C86933C2F38767211B - -Count = 464 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D072A33CD208DB99AB14D909A1BF0897BBF - -Count = 465 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D07EF21C68BF5EC7F2A4961B68029496EF7 - -Count = 466 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D0776F05D2331CCF223A799138017E5E1E3 - -Count = 467 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D077B25FD0AE25FAD0981AAE45D12D4CD17 - -Count = 468 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D07973839894C7515A881AD72AF468A4D9B - -Count = 469 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D07EEF8B938DAA70DC4AA38C5E5A0931EA0 - -Count = 470 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D0762488AA4FCC188C5AF00EF3B30751387 - -Count = 471 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D072062A7CF044F3B3F49089007C39BE0CA - -Count = 472 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D0778112E397F616842EA3CC09140575D38 - -Count = 473 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D07D47630637AA5913E08C05CCDB42791AE - -Count = 474 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D07E6FCCB1FCF858B628823FEB8F3A0A6A5 - -Count = 475 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D0704B1767322E1332AD9CDDFEE2100E899 - -Count = 476 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D07A9BFAC68A66449929CD88220E68557C0 - -Count = 477 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D07ACCCD21751E521A110531B624EBF00C6 - -Count = 478 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D07289D8BA5DACAB79D539DB2D21BB7A6CA - -Count = 479 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D07E640F80692C803552C76E7FA8576ECE6 - -Count = 480 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D073DCF811972107A058FAF4C552AA208A4 - -Count = 481 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D07F52C9AF07AEC487FB049F9ED735E5520 - -Count = 482 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D0706977ACE61E2C14711DCEB3D4E96AA80 - -Count = 483 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D075717E9C320CBE237365D20B326D552E9 - -Count = 484 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D0705273A6A151DC0FB5B471DE46A8157EC - -Count = 485 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D0700E94705ABD6157C88A5FA142FA2666F - -Count = 486 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D07281F1B2419E47AF58FE68568A62024F0 - -Count = 487 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D074AB564346A8B688A7BE3D5716EF8079E - -Count = 488 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D070238640A6BE9549CA18BF7F82F53363A - -Count = 489 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D07CD1A4DC32F98271DC6B57E2B2E7729A5 - -Count = 490 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D07BCE2D112AB93289ADC107DF8029F6D10 - -Count = 491 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D0785A1B7B97F535D591EA270617B5AFE3E - -Count = 492 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D07B57F63BD8A7B106CA409B3D506EA0787 - -Count = 493 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D07ED04CDD9732DD643AAC284D7F63B0A38 - -Count = 494 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D07DBFAB0CEFF636DFF4F8A2962EE667799 - -Count = 495 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D074438E36752F104EA7B879DBB71102278 - -Count = 496 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F5030FDAE23A2BED9CF994E56BBE1E9CC - -Count = 497 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F95CF2C411525B1A0EB3A16BECC0FB368 - -Count = 498 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F50DD27EA6D70543BEFCB3A2515CFA620 - -Count = 499 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079FC90CBC42A950D93201339F252B632934 - -Count = 500 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079FC4D91C6B7AC38618270068F82E5205C0 - -Count = 501 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F28C4D8E8D4E93EB92707FE0A7A0C854C - -Count = 502 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F51045859423B26D50C9249409C15D677 - -Count = 503 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079FDDB46BC5645DA3D409AA639E0CF3DB50 - -Count = 504 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F9F9E46AE9CD3102EEFA21CA2FF1D281D - -Count = 505 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079FC7EDCF58E7FD43534C964C347CD195EF - -Count = 506 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F6B8AD102E239BA2FAE6AD06888A15979 - -Count = 507 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F59002A7E5719A0732E89721DCF266E72 - -Count = 508 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079FBB4D9712BA7D183B7F67534B1D86204E - -Count = 509 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F16434D093EF862833A720E85DA039F17 - -Count = 510 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F13303376C9790AB0B6F997C77239C811 - -Count = 511 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F97616AC442569C8CF5373E7727316E1D - -Count = 512 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F59BC19670A5428448ADC6B5FB9F02431 - -Count = 513 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F82336078EA8C51142905C0F01624C073 - -Count = 514 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F4AD07B91E270636E16E375484FD89DF7 - -Count = 515 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079FB96B9BAFF97EEA56B776679872106257 - -Count = 516 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079FE8EB08A2B857C92690F7AC161A539A3E - -Count = 517 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079FBADBDB0B8D81EBEAFDED914156079F3B - -Count = 518 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079FBF15A664334A3E6D2E0F76B11324AEB8 - -Count = 519 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F97E3FA45817851E4294C09CD9AA6EC27 - -Count = 520 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079FF5498555F217439BDD4959D4527ECF49 - -Count = 521 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079FBDC4856BF3757F8D07217B5D13D5FEED - -Count = 522 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F72E6ACA2B7040C0C601FF28E12F1E172 - -Count = 523 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F031E3073330F038B7ABAF15D3E19A5C7 - -Count = 524 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F3A5D56D8E7CF7648B808FCC447DC36E9 - -Count = 525 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F0A8382DC12E73B7D02A33F703A6CCF50 - -Count = 526 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F52F82CB8EBB1FD520C680872CABDC2EF - -Count = 527 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F640651AF67FF46EEE920A5C7D2E0BF4E - -Count = 528 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079FFBC40206CA6D2FFBDD2D111E4D96EAAF - -Count = 529 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B9096D461FC1B70AE3938A394172992C0 - -Count = 530 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B5569058ECA9C7FD71D9BFB7C60C7C864 - -Count = 531 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B907B0E25B2C99A4C196AD7E7B907DD2C - -Count = 532 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B09AA958D76E91745F79272E787AB5238 - -Count = 533 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B047F35A4A57A486FD1A1853A829A7ECC - -Count = 534 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7BE862F1270B50F0CED1A613C8D6C4FE40 - -Count = 535 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B91A271969D82E8A2FA33A48230DDAD7B - -Count = 536 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B1D12420ABBE46DA3FF0B8E5CA03BA05C - -Count = 537 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B5F386F61436ADE591903F16053D55311 - -Count = 538 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B074BE69738448D24BA37A1F6D019EEE3 - -Count = 539 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7BAB2CF8CD3D80745858CB3DAA24692275 - -Count = 540 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B99A603B188A06E04D8289FDF63EE157E - -Count = 541 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B7BEBBEDD65C4D64C89C6BE89B14E5B42 - -Count = 542 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7BD6E564C6E141ACF4CCD3E34776CBE41B - -Count = 543 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7BD3961AB916C0C4C740587A05DEF1B31D - -Count = 544 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B57C7430B9DEF52FB0396D3B58BF91511 - -Count = 545 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B991A30A8D5EDE6337C7D869D15385F3D - -Count = 546 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B429549B735359F63DFA42D32BAECBB7F - -Count = 547 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B8A76525E3DC9AD19E042988AE310E6FB - -Count = 548 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B79CDB26026C7242141D78A5ADED8195B - -Count = 549 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B284D216D67EE0751665641D4B69BE132 - -Count = 550 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B7A7DF2C45238259D0B4C7C83FACFE437 - -Count = 551 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B7FB38FABECF3F01AD8AE9B73BFECD5B4 - -Count = 552 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B5745D38A5EC19F93DFEDE40F366E972B - -Count = 553 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B35EFAC9A2DAE8DEC2BE8B416FEB6B445 - -Count = 554 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B7D62ACA42CCCB1FAF180969FBF1D85E1 - -Count = 555 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7BB240856D68BDC27B96BE1F4CBE399A7E - -Count = 556 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7BC3B819BCECB6CDFC8C1B1C9F92D1DECB - -Count = 557 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7BFAFB7F173876B83F4EA91106EB144DE5 - -Count = 558 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7BCA25AB13CD5EF50AF402D2B296A4B45C - -Count = 559 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B925E057734083325FAC9E5B06675B9E3 - -Count = 560 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7BA4A07860B84688991F8148057E28C442 - -Count = 561 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B3B622BC915D4E18C2B8CFCDCE15E91A3 - -Count = 562 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B628C9B9BC62D788F90572FED135FE6931B - -Count = 563 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6249644A291BFF80E9738CB5FB2808C9BF - -Count = 564 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B628C76418263AA6572777D9960F1C8DCF7 - -Count = 565 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6215A7DA2AA78AE87B99853C60CF6453E3 - -Count = 566 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6218727A037419B751BFB6CBBDCA557F17 - -Count = 567 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62F46FBE80DA330FF0BFB15D4F9E0BFF9B - -Count = 568 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B628DAF3E314CE1179C9424EA057812ACA0 - -Count = 569 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62011F0DAD6A87929D911CC0DBE8F4A187 - -Count = 570 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62433520C6920921677714BFE71B1A52CA - -Count = 571 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B621B46A930E927721AD420EF7198D6EF38 - -Count = 572 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62B721B76AECE38B6636DC732D6CA623AE - -Count = 573 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6285AB4C1659C3913AB63FD1582B2114A5 - -Count = 574 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6267E6F17AB4A72972E7D1F00EF9815A99 - -Count = 575 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62CAE82B61302253CAA2C4ADC03E04E5C0 - -Count = 576 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62CF9B551EC7A33BF92E4F3482963EB2C6 - -Count = 577 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B624BCA0CAC4C8CADC56D819D32C33614CA - -Count = 578 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6285177F0F048E190D126AC81A5DF75EE6 - -Count = 579 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B625E980610E456605DB1B363B5F223BAA4 - -Count = 580 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62967B1DF9ECAA52278E55D60DABDFE720 - -Count = 581 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6265C0FDC7F7A4DB1F2FC0C4DD96171880 - -Count = 582 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6234406ECAB68DF86F08410F53FE54E0E9 - -Count = 583 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B626670BD63835BDAA3655B3204B200E5EC - -Count = 584 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6263BEC00C3D900F24B6B9D5F4F723D46F - -Count = 585 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B624B489C2D8FA260ADB1FAAA887EA196F0 - -Count = 586 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6229E2E33DFCCD72D245FFFA91B679B59E - -Count = 587 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62616FE303FDAF4EC49F97D818F7D2843A - -Count = 588 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62AE4DCACAB9DE3D45F8A951CBF6F69BA5 - -Count = 589 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62DFB5561B3DD532C2E20C5218DA1EDF10 - -Count = 590 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62E6F630B0E915470120BE5F81A3DB4C3E - -Count = 591 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62D628E4B41C3D0A349A159C35DE6BB587 - -Count = 592 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B628E534AD0E56BCC1B94DEAB372EBAB838 - -Count = 593 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62B8AD37C7692577A77196068236E7C599 - -Count = 594 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62276F646EC4B71EB2459BB25BA9919078 - -Count = 595 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629958B63F3127C40FBA975DE8211515BC0B - -Count = 596 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999D49EEDE114300C3B3FEB0C962FBE6AF - -Count = 597 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299585BE5756916E558B70F9C52BB3BF3E7 - -Count = 598 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299C18A7EDDAD36685159F7395285977CF3 - -Count = 599 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299CC5FDEF47EA5377B7FC4CE8F80A65007 - -Count = 600 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629920421A77D08F8FDA7FC3587DD4F8D08B - -Count = 601 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629959829AC6465D97B65456EF3732E183B0 - -Count = 602 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299D532A95A603B12B7516EC5E9A2078E97 - -Count = 603 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999718843198B5A14DB766BAD551E97DDA - -Count = 604 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299CF6B0DC7E39BF2301452EA43D225C028 - -Count = 605 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299630C139DE65F0B4CF6AE761F26550CBE - -Count = 606 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62995186E8E1537F1110764DD46A61D23BB5 - -Count = 607 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B3CB558DBE1BA95827A3F53CB3727589 - -Count = 608 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62991EC58F963A9ED3E062B6A8F274F7CAD0 - -Count = 609 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62991BB6F1E9CD1FBBD3EE3D31B0DCCD9DD6 - -Count = 610 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999FE7A85B46302DEFADF3980089C53BDA - -Count = 611 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299513ADBF80E329927D218CD28170471F6 - -Count = 612 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62998AB5A2E7EEEAE07771C16687B8D095B4 - -Count = 613 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62994256B90EE616D20D4E27D33FE12CC830 - -Count = 614 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B1ED5930FD185B35EFB2C1EFDCE43790 - -Count = 615 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299E06DCA3DBC317845C8330A61B4A7CFF9 - -Count = 616 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B25D199489E75A89A5293736F8F3CAFC - -Count = 617 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B79364FB372C8F0E76CBD0C6BDD0FB7F - -Count = 618 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999F6538DA851EE0877188AFBA3452B9E0 - -Count = 619 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299FDCF47CAF671F2F8858DFFA3FC8A9A8E - -Count = 620 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B54247F4F713CEEE5FE5DD2ABD21AB2A - -Count = 621 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997A606E3DB362BD6F38DB54F9BC05B4B5 - -Count = 622 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62990B98F2EC3769B2E8227E572A90EDF000 - -Count = 623 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629932DB9447E3A9C72BE0CC5AB3E928632E - -Count = 624 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62990205404316818A1E5A67990794989A97 - -Count = 625 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62995A7EEE27EFD74C3154ACAE0564499728 - -Count = 626 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62996C8093306399F78DB1E403B07C14EA89 - -Count = 627 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299F342C099CE0B9E9885E9B769E362BF68 - -Count = 628 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997969C2D9DA08ABA81C8EFB9CDABF0ECC43 - -Count = 629 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AC3D08353E2CA765AA58C432C8E096E7 - -Count = 630 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979692F039E467942FEAEA9E8A9112083AF - -Count = 631 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979F0FE98368259CFF740514DA92F8C0CBB - -Count = 632 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979FD2B381F51CA90DD6662BA742ABD204F - -Count = 633 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299791136FC9CFFE0287C66652C867EE3A0C3 - -Count = 634 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997968F67C2D693230104DF09BCC98FAF3F8 - -Count = 635 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979E4464FB14F54B51148C8B112081CFEDF - -Count = 636 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A66C62DAB7DA06EBAEC0CE2EFBF20D92 - -Count = 637 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979FE1FEB2CCCF455960DF49EB8783EB060 - -Count = 638 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299795278F576C930ACEAEF0802E48C4E7CF6 - -Count = 639 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997960F20E0A7C10B6B66FEBA091CBC94BFD - -Count = 640 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997982BFB36691740EFE3E0581C7196905C1 - -Count = 641 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299792FB1697D15F174467B10DC09DEECBA98 - -Count = 642 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299792AC21702E2701C75F79B454B76D6ED9E - -Count = 643 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AE934EB0695F8A49B455ECFB23DE4B92 - -Count = 644 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979604E3D13215D3E81CBBEB9D3BD1F01BE - -Count = 645 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979BBC1440CC18547D16867127C12CBE5FC - -Count = 646 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997973225FE5C97975AB5781A7C44B37B878 - -Count = 647 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798099BFDBD277FC93F614B51476FF47D8 - -Count = 648 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979D1192CD6935EDFE3D1957E9A1EBCBFB1 - -Count = 649 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798329FF7FA688FD2FBC8F43CD52E8BAB4 - -Count = 650 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997986E78210184328A86F6DA43D17CB8B37 - -Count = 651 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AE11DE31AA714721682EDB419E49C9A8 - -Count = 652 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979CCBBA121D91E555E9C2B8B585691EAC6 - -Count = 653 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798436A11FD87C69484643A9D1173ADB62 - -Count = 654 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299794B1488D69C0D1AC9217D2002161EC4FD - -Count = 655 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299793AEC14071806154E3BD823D13AF68048 - -Count = 656 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997903AF72ACCCC6608DF96A2E4843331366 - -Count = 657 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299793371A6A839EE2DB843C1EDFC3E83EADF - -Count = 658 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299796B0A08CCC0B8EB974D0ADAFECE52E760 - -Count = 659 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299795DF475DB4CF6502BA842774BD60F9AC1 - -Count = 660 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979C2362672E164393E9C4FC3924979CF20 - -Count = 661 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B9A593097205AA96CD53AB48F8592FAC - -Count = 662 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27C5A42E64482A5EFE9F0F3A08FB77508 - -Count = 663 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B948494D3CD74074ED01DF3B56776040 - -Count = 664 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22099D2E5F8F7CD7D03F97A3B68DBEF54 - -Count = 665 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22D4C72CC2B64925725CA8DE66DEAC3A0 - -Count = 666 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2C151B64F854E2AF625CD1B1439B4432C - -Count = 667 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B89136FE139C329A0E58AC5EDFAD1017 - -Count = 668 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A23421056235FAB79B0B6086804F4B1D30 - -Count = 669 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2760B2809CD740461ED68F9BCBCA5EE7D - -Count = 670 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22E78A1FFB65A571C4E5CA92A3F69538F - -Count = 671 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2821FBFA5B39EAE60ACA03576CB199F19 - -Count = 672 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B09544D906BEB43C2C4397038C9EA812 - -Count = 673 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A252D8F9B5EBDA0C747DADB6555E3EE62E - -Count = 674 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2FFD623AE6F5F76CC38B8EB9B99BB5977 - -Count = 675 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2FAA55DD198DE1EFFB43372D931810E71 - -Count = 676 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27EF4046313F188C3F7FDDB696489A87D - -Count = 677 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B02977C05BF33C0B88168E41FA48E251 - -Count = 678 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A26BA60EDFBB2B455B2BCF25EE559C0613 - -Count = 679 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2A3451536B3D77721142990560C605B97 - -Count = 680 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A250FEF508A8D9FE19B5BC828631A8A437 - -Count = 681 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2017E6605E9F0DD69923D490859EB5C5E - -Count = 682 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2534EB5ACDC26FFA5FF27745F15BF595B - -Count = 683 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A25680C8C362ED2A222CC593AF509C68D8 - -Count = 684 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27E7694E2D0DF45AB2B86ECD3D91E2A47 - -Count = 685 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A21CDCEBF2A3B057D4DF83BCCA11C60929 - -Count = 686 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A25451EBCCA2D26BC205EB9E43506D388D - -Count = 687 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A29B73C205E6A3184362D5179051492712 - -Count = 688 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2EA8B5ED462A817C4787014437DA163A7 - -Count = 689 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2D3C8387FB6686207BAC219DA0464F089 - -Count = 690 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2E316EC7B43402F320069DA6E79D40930 - -Count = 691 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2BB6D421FBA16E91D0EA2ED6C8905048F - -Count = 692 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A28D933F08365852A1EBEA40D99158792E - -Count = 693 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A212516CA19BCA3BB4DFE7F4000E2E2CCF - -Count = 694 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240434EE6A09FEDD4F51F39952D0B84AB3E - -Count = 695 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24086B1374FA96ADB8C3B9ACDC57C6AF19A - -Count = 696 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24043A33CE4D13F3E173F6BE15EA5AAE4D2 - -Count = 697 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240DA72A74C151FB31ED193445E9B066BC6 - -Count = 698 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240D7A70765C68CEC34F7A0B3839E374732 - -Count = 699 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403BBAC3E668A65495F7A72571CA69C7BE - -Count = 700 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240427A4357FE744CF9DC32923B2C709485 - -Count = 701 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240CECA70CBD812C9F8D90AB8E5BC9699A2 - -Count = 702 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2408CE05DA0209C7A023F02C7D94F786AEF - -Count = 703 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240D493D4565BB2297F9C36974FCCB4D71D - -Count = 704 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24078F4CA0C5E76D0037ECA0B1338C41B8B - -Count = 705 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2404A7E3170EB56CA5FFE29A9667F432C80 - -Count = 706 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240A8338C1C06327217AFC78830ADE362BC - -Count = 707 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240053D560782B708AFEAD2D5FE6A66DDE5 - -Count = 708 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240004E28787536609C66594CBCC25C8AE3 - -Count = 709 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240841F71CAFE19F6A02597E50C97542CEF - -Count = 710 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2404AC20269B61B42685A7CB024099566C3 - -Count = 711 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240914D7B7656C33B38F9A51B8BA6418281 - -Count = 712 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24059AE609F5E3F0942C643AE33FFBDDF05 - -Count = 713 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AA1580A14531807A67D6BCE3C27520A5 - -Count = 714 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240FB9513AC0418A30A4057776DAA36D8CC - -Count = 715 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240A9A5C00531CE81C62D4D4A3AE662DDC9 - -Count = 716 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AC6BBD6A8F055441FEAFADCAA341EC4A - -Count = 717 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240849DE14B3D373BC8F9ECD2B62AC3AED5 - -Count = 718 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240E6379E5B4E5829B70DE982AFE21B8DBB - -Count = 719 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AEBA9E654F3A15A1D781A026A3B0BC1F - -Count = 720 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2406198B7AC0B4B6620B0BF29F5A294A380 - -Count = 721 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24010602B7D8F4069A7AA1A2A268E7CE735 - -Count = 722 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24029234DD65B801C6468A827BFF7B9741B - -Count = 723 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24019FD99D2AEA85151D203E40B8A098DA2 - -Count = 724 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240418637B657FE977EDCC8D3097AD8801D - -Count = 725 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24077784AA1DBB02CC239807EBC6285FDBC - -Count = 726 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240E8BA1908762245D70D8DCA65FDF3A85D - -Count = 727 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D546FE67094BB75016786E3EA9E6A5BCD - -Count = 728 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9190379FA23C7A784325BB02E9840169 - -Count = 729 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D54823C34DA699FE347D4979930441421 - -Count = 730 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DCD53A79C1E4912EAA92C32990EE89B35 - -Count = 731 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DC08607B5CDDA4DC08F1FC5440BD9B7C1 - -Count = 732 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D2C9BC33663F0F5618F1853B65F87374D - -Count = 733 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D555B4387F522ED0DA48DE4FCB99E6476 - -Count = 734 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DD9EB701BD344680CA1B5CE2229786951 - -Count = 735 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9BC15D702BCADBF647BDB11EDA969A1C - -Count = 736 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DC3B2D48650E4888BE489E188595A27EE - -Count = 737 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D6FD5CADC552071F706757DD4AD2AEB78 - -Count = 738 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D5D5F31A0E0006BAB8696DFA1EAADDC73 - -Count = 739 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBF128CCC0D64D3E3D778FEF7380D924F - -Count = 740 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D121C56D789E1A95B926DA339FF882D16 - -Count = 741 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D176F28A87E60C1681EE63A7B57B27A10 - -Count = 742 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D933E711AF54F57545D2893CB02BADC1C - -Count = 743 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D5DE302B9BD4DE39C22C3C6E39C7B9630 - -Count = 744 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D866C7BA65D959ACC811A6D4C33AF7272 - -Count = 745 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D4E8F604F5569A8B6BEFCD8F46A532FF6 - -Count = 746 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBD3480714E67218E1F69CA24579BD056 - -Count = 747 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DECB4137C0F4E02FE38E801AA3FD8283F - -Count = 748 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBE84C0D53A98203255F23CFD738C2D3A - -Count = 749 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBB4ABDBA8453F5B58610DB0D36AF1CB9 - -Count = 750 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D93BCE19B36619A3C8153A471BF2D5E26 - -Count = 751 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DF1169E8B450E88437556F46877F57D48 - -Count = 752 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DB99B9EB5446CB455AF3ED6E1365E4CEC - -Count = 753 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D76B9B77C001DC7D4C8005F32377A5373 - -Count = 754 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D07412BAD8416C853D2A55CE11B9217C6 - -Count = 755 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D3E024D0650D6BD9010175178625784E8 - -Count = 756 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D0EDC9902A5FEF0A5AABC92CC1FE77D51 - -Count = 757 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D56A737665CA8368AA477A5CEEF3670EE - -Count = 758 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D60594A71D0E68D36413F087BF76B0D4F - -Count = 759 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DFF9B19D87D74E4237532BCA2681D58AE - -Count = 760 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9F02DA748370296F34EA79F4E5497D6D - -Count = 761 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F5AFD0B9BB5F726161049211C92A727C9 - -Count = 762 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9FEF0030CDA2C38D14B80D874B673281 - -Count = 763 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F063E9B9809824E84FA40A88775CBBD95 - -Count = 764 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F0BEB3BB1DA1111AEDC735F5A70FA9161 - -Count = 765 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FE7F6FF32743BA90FDC74C9A824A411ED - -Count = 766 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9E367F83E2E9B163F7E17EE2C2BD42D6 - -Count = 767 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F12864C1FC48F3462F2D9543C525B4FF1 - -Count = 768 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F50AC61743C01879814D12B00A1B5BCBC - -Count = 769 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F08DFE882472FD4E5B7E57B962279014E - -Count = 770 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FA4B8F6D842EB2D995519E7CAD609CDD8 - -Count = 771 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F96320DA4F7CB37C5D5FA45BF918EFAD3 - -Count = 772 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F747FB0C81AAF8F8D841464E9432EB4EF - -Count = 773 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FD9716AD39E2AF535C101392784AB0BB6 - -Count = 774 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FDC0214AC69AB9D064D8AA0652C915CB0 - -Count = 775 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F58534D1EE2840B3A0E4409D57999FABC - -Count = 776 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F968E3EBDAA86BFF271AF5CFDE758B090 - -Count = 777 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F4D0147A24A5EC6A2D276F752488C54D2 - -Count = 778 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F85E25C4B42A2F4D8ED9042EA11700956 - -Count = 779 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F7659BC7559AC7DE04C05503A2CB8F6F6 - -Count = 780 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F27D92F7818855E906B849BB444FB0E9F - -Count = 781 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F75E9FCD12D537C5C069EA6E308AF0B9A - -Count = 782 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F702781BE9398A9DBD57C41134D8C3A19 - -Count = 783 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F58D1DD9F21AAC652D23F3E6FC40E7886 - -Count = 784 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F3A7BA28F52C5D42D263A6E760CD65BE8 - -Count = 785 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F72F6A2B153A7E83BFC524CFF4D7D6A4C - -Count = 786 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FBDD48B7817D69BBA9B6CC52C4C5975D3 - -Count = 787 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FCC2C17A993DD943D81C9C6FF60B13166 - -Count = 788 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FF56F7102471DE1FE437BCB661974A248 - -Count = 789 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FC5B1A506B235ACCBF9D008D264C45BF1 - -Count = 790 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9DCA0B624B636AE4F71B3FD09415564E - -Count = 791 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FAB347675C72DD158125392658C482BEF - -Count = 792 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F34F625DC6ABFB84D265E26BC133E7E0E - -Count = 793 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEB338400A1628D9BDBA44BD09814A472 - -Count = 794 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2ECC55EF97E582E2FF071338EFFAFED6 - -Count = 795 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEBDE5E44EFB06779FBF63FA3363AEB9E - -Count = 796 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F720FC5EC2B90EA70150E9AA30896648A - -Count = 797 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F7FDA65C5F803B55A333D6D7E0DA7487E - -Count = 798 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F93C7A14656290DFB333AFB8C59F9C8F2 - -Count = 799 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEA0721F7C0FB159718AF4CC6BFE09BC9 - -Count = 800 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F66B7126BE69D90961D9766182F0696EE - -Count = 801 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F249D3F001E13236CFB9F1924DCE865A3 - -Count = 802 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F7CEEB6F6653D701158AB49B25F24D851 - -Count = 803 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FD089A8AC60F9896DBA57D5EEAB5414C7 - -Count = 804 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE20353D0D5D993313AB4779BECD323CC - -Count = 805 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F004EEEBC38BD2B796B5A56CD3E736DF0 - -Count = 806 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FAD4034A7BC3851C12E4F0B03F9F6D2A9 - -Count = 807 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FA8334AD84BB939F2A2C4924151CC85AF - -Count = 808 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2C62136AC096AFCEE10A3BF104C423A3 - -Count = 809 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE2BF60C988941B069EE16ED99A05698F - -Count = 810 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F393019D6684C62563D38C57635D18DCD - -Count = 811 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FF1D3023F60B0502C02DE70CE6C2DD049 - -Count = 812 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F0268E2017BBED914A34B621E51E52FE9 - -Count = 813 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F53E8710C3A97FA6484CAA99039A6D780 - -Count = 814 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F01D8A2A50F41D8A8E9D094C775F2D285 - -Count = 815 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F0416DFCAB18A0D2F3A32733730D1E306 - -Count = 816 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2CE083EB03B862A63D710C4BB953A199 - -Count = 817 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F4E4AFCFB70D770D9C9745C52718B82F7 - -Count = 818 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F06C7FCC571B54CCF131C7EDB3020B353 - -Count = 819 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FC9E5D50C35C43F4E7422F7083104ACCC - -Count = 820 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FB81D49DDB1CF30C96E87F4DB1DECE879 - -Count = 821 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F815E2F76650F450AAC35F94264297B57 - -Count = 822 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FB180FB729027083F169E3AF6199982EE - -Count = 823 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE9FB55166971CE1018550DF4E9488F51 - -Count = 824 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FDF052801E53F75ACFD1DA041F115F2F0 - -Count = 825 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F1011121314151617 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F40C77BA848AD1CB9C91014986E63A711 - -Count = 826 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C64EED4250F2974316283EDF1239D4504 - -Count = 827 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA11105CA39AE7B484620B51954731FA0 - -Count = 828 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C64030E6141FB9ED342D199828DB30AE8 - -Count = 829 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CFDD295C985DB13DAAC293C82B31F85FC - -Count = 830 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CF00735E056484CF08A1ACB5FB62EA908 - -Count = 831 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C1C1AF163F862F4518A1D5DADE2702984 - -Count = 832 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C65DA71D26EB0EC3DA188EAE704697ABF - -Count = 833 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CE96A424E48D6693CA4B0C039948F7798 - -Count = 834 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CAB406F25B058DAC642B8BF05676184D5 - -Count = 835 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CF333E6D3CB7689BBE18CEF93E4AD3927 - -Count = 836 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C5F54F889CEB270C7037073CF10DDF5B1 - -Count = 837 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C6DDE03F57B926A9B8393D1BA575AC2BA - -Count = 838 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8F93BE9996F6D2D3D27DF0EC85FA8C86 - -Count = 839 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C229D64821273A86B9768AD22427F33DF - -Count = 840 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C27EE1AFDE5F2C0581BE33460EA4564D9 - -Count = 841 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA3BF434F6EDD5664582D9DD0BF4DC2D5 - -Count = 842 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C6D6230EC26DFE2AC27C6C8F8218C88F9 - -Count = 843 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CB6ED49F3C6079BFC841F63578E586CBB - -Count = 844 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C7E0E521ACEFBA986BBF9D6EFD7A4313F - -Count = 845 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8DB5B224D5F520BE1A6CC43FEA6CCE9F - -Count = 846 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CDC35212994DC03CE3DED0FB1822F36F6 - -Count = 847 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8E05F280A10A210250F732E6CE7B33F3 - -Count = 848 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8BCB8FEF1FC1F4858315D5168B580270 - -Count = 849 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA33DD3CEADF39B0C8456AA6A02DA40EF - -Count = 850 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CC197ACDEDE9C89737053FA73CA026381 - -Count = 851 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C891AACE0DFFEB565AA3BD8FA8BA95225 - -Count = 852 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C463885299B8FC6E4CD0551298A8D4DBA - -Count = 853 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C37C019F81F84C963D7A052FAA665090F - -Count = 854 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C0E837F53CB44BCA015125F63DFA09A21 - -Count = 855 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C3E5DAB573E6CF195AFB99CD7A2106398 - -Count = 856 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C66260533C73A37BAA172ABD552C16E27 - -Count = 857 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C50D878244B748C06443A06604A9C1386 - -Count = 858 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CCF1A2B8DE6E6E5137037B2B9D5EA4667 - -Count = 859 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA07F036BA47E86F5A423E3F84EB9C614F - -Count = 860 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC20FE755716F6023669D676C9C723BEB - -Count = 861 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA071DECFE093A85B8626C4BF745B22EA3 - -Count = 862 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA9ECC7756CD1A08B18C94EEF77B1EA1B7 - -Count = 863 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA9319D77F1E89579BAAA7192A7E2F8D43 - -Count = 864 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA7F0413FCB0A3EF3AAAA08FD82A710DCF - -Count = 865 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA06C4934D2671F75681353892CC685EF4 - -Count = 866 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA8A74A0D100177257840D124C5C8E53D3 - -Count = 867 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC85E8DBAF899C1AD62056D70AF60A09E - -Count = 868 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA902D044C83B792D0C1313DE62CAC1D6C - -Count = 869 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA3C4A1A1686736BAC23CDA1BAD8DCD1FA - -Count = 870 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0EC0E16A335371F0A32E03CF9F5BE6F1 - -Count = 871 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEC8D5C06DE37C9B8F2C022994DFBA8CD - -Count = 872 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA4183861D5AB2B300B7D57F578A7E1794 - -Count = 873 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA44F0F862AD33DB333B5EE61522444092 - -Count = 874 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC0A1A1D0261C4D0F78904FA5774CE69E - -Count = 875 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0E7CD2736E1EF9C7077B1A8DE98DACB2 - -Count = 876 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAD5F3AB6C8EC68097A4A2B122465948F0 - -Count = 877 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA1D10B085863AB2ED9B44049A1FA51574 - -Count = 878 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEEAB50BB9D343BD53AD1164A226DEAD4 - -Count = 879 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBABF2BC3B6DC1D18A51D50DDC44A2E12BD - -Count = 880 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAED1B101FE9CB3A69704AE093067A17B8 - -Count = 881 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAE8D56D705700EFEEA3A807634359263B - -Count = 882 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC0233151E5328067A4EB781FCADB64A4 - -Count = 883 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAA2894E41965D921850EE2806020347CA - -Count = 884 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEA044E7F973FAE0E8A860A8F43A8766E - -Count = 885 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA252667B6D34EDD8FEDB8835C428C69F1 - -Count = 886 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA54DEFB675745D208F71D808F6E642D44 - -Count = 887 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA6D9D9DCC8385A7CB35AF8D1617A1BE6A - -Count = 888 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA5D4349C876ADEAFE8F044EA26A1147D3 - -Count = 889 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0538E7AC8FFB2CD181CF79A09AC04A6C - -Count = 890 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA33C69ABB03B5976D6487D415829D37CD - -Count = 891 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAAC04C912AE27FE78508A60CC1DEB622C - -Count = 892 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250F0927D72D857E36CAD703B28EF139FA - -Count = 893 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25CAF6F6381B02714FEE745B5AF91F635E - -Count = 894 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250FE4FD93635794D4EA8577C120DF7616 - -Count = 895 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259635663BA77719DD047DD2C11E73F902 - -Count = 896 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259BE0C61274E446F7224E251C1B42D5F6 - -Count = 897 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2577FD0291DACEFE562249B3EE4F1C557A - -Count = 898 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250E3D82204C1CE63A09DC04A4A9050641 - -Count = 899 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25828DB1BC6A7A633B0CE42E7A39E30B66 - -Count = 900 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C0A79CD792F4D0C1EAEC5146CA0DF82B - -Count = 901 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2598D41521E9DA83BC49D801D049C145D9 - -Count = 902 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2534B30B7BEC1E7AC0AB249D8CBDB1894F - -Count = 903 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250639F007593E609C2BC73FF9FA36BE44 - -Count = 904 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E4744D6BB45AD8D47A291EAF2896F078 - -Count = 905 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25497A977030DFA26C3F3C4361EF134F21 - -Count = 906 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA254C09E90FC75ECA5FB3B7DA2347291827 - -Count = 907 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C858B0BD4C715C63F07973931221BE2B - -Count = 908 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250685C31E0473E8AB8F9226BB8CE0F407 - -Count = 909 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25DD0ABA01E4AB91FB2C4B8D1423341045 - -Count = 910 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2515E9A1E8EC57A38113AD38AC7AC84DC1 - -Count = 911 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E65241D6F7592AB9B2382A7C4700B261 - -Count = 912 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25B7D2D2DBB67009C995B9E1F22F434A08 - -Count = 913 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E5E2017283A62B05F8A3DCA563174F0D - -Count = 914 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E02C7C1D3D6DFE822B413B5526347E8E - -Count = 915 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C8DA203C8F5F910B2C024429AFB63C11 - -Count = 916 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25AA705F2CFC308374D8071430676E1F7F - -Count = 917 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E2FD5F12FD52BF62026F36B926C52EDB - -Count = 918 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA252DDF76DBB923CCE36551BF6A27E13144 - -Count = 919 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA255C27EA0A3D28C3647FF4BCB90B0975F1 - -Count = 920 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2565648CA1E9E8B6A7BD46B12072CCE6DF - -Count = 921 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2555BA58A51CC0FB9207ED72940F7C1F66 - -Count = 922 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250DC1F6C1E5963DBD09264596FFAD12D9 - -Count = 923 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA253B3F8BD669D88601EC6EE823E7F06F78 - -Count = 924 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25A4FDD87FC44AEF14D8635CFA78863A99 - -Count = 925 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCE72A8718C1BF9A53B646BE0293BB8CF - -Count = 926 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D0B8D799EBA9CF6DC1FC733085ED5E26B - -Count = 927 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCE9F7235C2C913471B361F938715F723 - -Count = 928 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D574EE99D06E99E4EF5CEBA93B9B97837 - -Count = 929 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D5A9B49B4D57AC164D3FD4D4EBC8854C3 - -Count = 930 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DB6868D377B5079C5D3FADBBCE8D6D44F - -Count = 931 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCF460D86ED8261A9F86F6CF60ECF8774 - -Count = 932 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D43F63E1ACBE4E4A8FD5746289E298A53 - -Count = 933 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D01DC1371336A57521B5F39146DC7791E - -Count = 934 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D59AF9A874844042FB86B6982EE0BC4EC - -Count = 935 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DF5C884DD4D80FD535A97F5DE1A7B087A - -Count = 936 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DC7427FA1F8A0E70FDA7457AB5DFC3F71 - -Count = 937 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D250FC2CD15C45F478B9A76FD8F5C714D - -Count = 938 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D880118D6914125FFCE8F2B3348D9CE14 - -Count = 939 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D8D7266A966C04DCC4204B271E0E39912 - -Count = 940 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D09233F1BEDEFDBF001CA1BC1B5EB3F1E - -Count = 941 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DC7FE4CB8A5ED6F387E214EE92B2A7532 - -Count = 942 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D1C7135A745351668DDF8E54684FE9170 - -Count = 943 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DD4922E4E4DC92412E21E50FEDD02CCF4 - -Count = 944 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2729CE7056C7AD2A438B422EE0CA3354 - -Count = 945 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D76A95D7D17EE8E5A640A89A08889CB3D - -Count = 946 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D24998ED42238AC960910B4F7C4DDCE38 - -Count = 947 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2157F3BB9CF37911DAF2530781FEFFBB - -Count = 948 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D09A1AF9A2EC11698DDB12C7B087CBD24 - -Count = 949 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D6B0BD08A5DAE04E729B47C62C0A49E4A - -Count = 950 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2386D0B45CCC38F1F3DC5EEB810FAFEE - -Count = 951 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DECA4F97D18BD4B7094E2D738802BB071 - -Count = 952 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D9D5C65AC9CB644F78E47D4EBACC3F4C4 - -Count = 953 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DA41F0307487631344CF5D972D50667EA - -Count = 954 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D94C1D703BD5E7C01F65E1AC6A8B69E53 - -Count = 955 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCCBA79674408BA2EF8952DC4586793EC - -Count = 956 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DFA440470C84601921DDD8071403AEE4D - -Count = 957 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D658657D965D4688729D034A8DF4CBBAC - -Count = 958 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4AE2A91E60E75157A9577109369DB8DF - -Count = 959 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8F1D78F156605E2E8DF429E14173E27B - -Count = 960 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4A0F735A2E35BBB58905057A98B3F733 - -Count = 961 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABD3DEE8F2EA1536BC67FDA07AA61F7827 - -Count = 962 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABDE0B48DB3986699641CE57A7A32E54D3 - -Count = 963 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB32168C5897ACD13741C9C155F770D45F - -Count = 964 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4BD60CE9017EC95B6A5C761F11698764 - -Count = 965 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABC7663F7527184C5A6F645CC1818F8A43 - -Count = 966 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB854C121EDF96FFA0896C23FD7261790E - -Count = 967 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABDD3F9BE8A4B8ACDD2A58736BF1ADC4FC - -Count = 968 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB715885B2A17C55A1C8A4EF3705DD086A - -Count = 969 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB43D27ECE145C4FFD48474D42425A3F61 - -Count = 970 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA19FC3A2F938F7B519A96C1490FA715D - -Count = 971 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB0C9119B97DBD8D0D5CBC31DA577FCE04 - -Count = 972 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB09E267C68A3CE53ED037A898FF459902 - -Count = 973 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8DB33E740113730293F90128AA4D3F0E - -Count = 974 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB436E4DD74911C7CAEC125400348C7522 - -Count = 975 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB98E134C8A9C9BE9A4FCBFFAF9B589160 - -Count = 976 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB50022F21A1358CE0702D4A17C2A4CCE4 - -Count = 977 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA3B9CF1FBA3B05D8D1B858C7FF6C3344 - -Count = 978 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABF2395C12FB1226A8F6399349972FCB2D - -Count = 979 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA0098FBBCEC404649B23AE1EDB7BCE28 - -Count = 980 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA5C7F2D4700FD1E348C149EE9E58FFAB - -Count = 981 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8D31AEF5C23DBE6A4F82369217DABD34 - -Count = 982 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABEF9BD1E5B152AC15BB87668BDF029E5A - -Count = 983 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA716D1DBB030900361EF44029EA9AFFE - -Count = 984 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6834F812F441E38206D1CDD19F8DB061 - -Count = 985 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB19CC64C3704AEC051C74CE02B365F4D4 - -Count = 986 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB208F0268A48A99C6DEC6C39BCAA067FA - -Count = 987 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB1051D66C51A2D4F3646D002FB7109E43 - -Count = 988 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB482A7808A8F412DC6AA6372D47C193FC - -Count = 989 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB7ED4051F24BAA9608FEE9A985F9CEE5D - -Count = 990 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABE11656B68928C075BBE32E41C0EABBBC - -Count = 991 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4D70746F2D2879F989505D58F7ACA95C - -Count = 992 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F888FA5801BAF7680ADF305B08042F3F8 - -Count = 993 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4D9DAE2B63FA931BA902292B5982E6B0 - -Count = 994 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FD44C3583A7DA1E1247FA8C2B672E69A4 - -Count = 995 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FD99995AA7449413861C97BF6621F4550 - -Count = 996 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F35845129DA63F99961CEED043641C5DC - -Count = 997 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4C44D1984CB1E1F54A5B5A4ED05896E7 - -Count = 998 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FC0F4E2046AD764F44F63709040BE9BC0 - -Count = 999 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F82DECF6F9259D70EA96B0FACB350688D - -Count = 1000 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FDAAD4699E97784730A5F5F3A309CD57F - -Count = 1001 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F76CA58C3ECB37D0FE8A3C366C4EC19E9 - -Count = 1002 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4440A3BF5993675368406113836B2EE2 - -Count = 1003 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA60D1ED3B4F7DF1B39AE404551CB60DE - -Count = 1004 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F0B03C4C83072A5A37CBB1D8B964EDF87 - -Count = 1005 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F0E70BAB7C7F3CD90F03084C93E748881 - -Count = 1006 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F8A21E3054CDC5BACB3FE2D796B7C2E8D - -Count = 1007 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F44FC90A604DEEF64CC157851F5BD64A1 - -Count = 1008 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F9F73E9B9E40696346FCCD3FE5A6980E3 - -Count = 1009 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F5790F250ECFAA44E502A66460395DD67 - -Count = 1010 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA42B126EF7F42D76F1BF74963E5D22C7 - -Count = 1011 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FF5AB8163B6DD0E06D63EBF18561EDAAE - -Count = 1012 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA79B52CA830B2CCABB24824F1A4ADFAB - -Count = 1013 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA2552FA53DC0F94D68C665BF5F69EE28 - -Count = 1014 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F8AA373848FF296C46F851AC3D6EBACB7 - -Count = 1015 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FE8090C94FC9D84BB9B804ADA1E338FD9 - -Count = 1016 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA0840CAAFDFFB8AD41E868535F98BE7D - -Count = 1017 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F6FA62563B98ECB2C26D6E1805EBCA1E2 - -Count = 1018 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F1E5EB9B23D85C4AB3C73E2537254E557 - -Count = 1019 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F271DDF19E945B168FEC1EFCA0B917679 - -Count = 1020 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F17C30B1D1C6DFC5D446A2C7E76218FC0 - -Count = 1021 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4FB8A579E53B3A724AA11B7C86F0827F - -Count = 1022 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7946D86E697581CEAFE9B6C99EADFFDE - -Count = 1023 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FE6848BC7C4E7E8DB9BE4021001DBAA3F - -Count = 1024 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7E4CC94143EC866BA90EF8B4A00D3652 - -Count = 1025 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EBBB318AE756B89128DADA05CD7E36CF6 - -Count = 1026 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7EA113050D3E6C89895C8CC70E2379BE - -Count = 1027 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EE77088ADC91EE18067A429C7308FF6AA - -Count = 1028 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EEAA528841A8DBEAA4197DE1A35BEDA5E - -Count = 1029 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E06B8EC07B4A7060B419048E861E05AD2 - -Count = 1030 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7F786CB622751E676A05FFA287F909E9 - -Count = 1031 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EF3C85F2A04139B666F3DD57C171F04CE - -Count = 1032 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB1E27241FC9D289C8935AA40E4F1F783 - -Count = 1033 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EE991FBB787B37BE12A01FAD6673D4A71 - -Count = 1034 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E45F6E5ED8277829DC8FD668A934D86E7 - -Count = 1035 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E777C1E91375798C1481EC4FFD4CAB1EC - -Count = 1036 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9531A3FDDA33208919F0E5A9066AFFD0 - -Count = 1037 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E383F79E65EB65A315CE5B867C1EF4089 - -Count = 1038 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E3D4C0799A9373202D06E212569D5178F - -Count = 1039 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB91D5E2B2218A43E93A088953CDDB183 - -Count = 1040 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E77C02D886A1A10F6EC4BDDBDA21CFBAF - -Count = 1041 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EAC4F54978AC269A64F9276120DC81FED - -Count = 1042 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E64AC4F7E823E5BDC7074C3AA54344269 - -Count = 1043 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9717AF409930D2E4D1E1D17A69FCBDC9 - -Count = 1044 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EC6973C4DD819F194F6601AF401BF45A0 - -Count = 1045 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E94A7EFE4EDCFD3589B7A27A34DEB40A5 - -Count = 1046 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9169928B530406DF4898C05308C87126 - -Count = 1047 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB99FCEAAE13669564FDBBF2F814A33B9 - -Count = 1048 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EDB35B1BA92597B29BBDEEF36499210D7 - -Count = 1049 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E93B8B184933B473F61B6CDBF08392173 - -Count = 1050 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5C9A984DD74A34BE0688446C091D3EEC - -Count = 1051 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E2D62049C53413B391C2D47BF25F57A59 - -Count = 1052 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E1421623787814EFADE9F4A265C30E977 - -Count = 1053 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E24FFB63372A903CF64348992218010CE - -Count = 1054 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7C8418578BFFC5E06AFFBE90D1511D71 - -Count = 1055 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E4A7A654007B17E5C8FB71325C90C60D0 - -Count = 1056 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7ED5B836E9AA231749BBBAA7FC567A3531 - -Count = 1057 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDD94B5A9DC1B1E0E4B67D163F605735C - -Count = 1058 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B186B6446EA9C11776FC4898B81EB29F8 - -Count = 1059 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDD796FED92C9F4EC6B35A510582B3CB0 - -Count = 1060 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B44A8F44556E979E585CD00106687B3A4 - -Count = 1061 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B497D546C857A26CFA3FEF7CD63B69F50 - -Count = 1062 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BA56090EF2B509E6EA3F9613F37E81FDC - -Count = 1063 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDCA0105EBD828602886CD675D1F14CE7 - -Count = 1064 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B501023C29BE403038D54FCAB411741C0 - -Count = 1065 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 0001020304050607 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B123A0EA9636AB0F96B5C8397B2F9B28D - -Count = 1066 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B4A49875F1844E384C868D30131350F7F - -Count = 1067 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 00010203040506070809 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BE62E99051D801AF82A944F5DC545C3E9 - -Count = 1068 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BD4A46279A8A000A4AA77ED2882C2F4E2 - -Count = 1069 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B36E9DF1545C4B8ECFB99CC7E5062BADE - -Count = 1070 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B9BE7050EC141C254BE8C91B097E70587 - -Count = 1071 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B9E947B7136C0AA67320708F23FDD5281 - -Count = 1072 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B1AC522C3BDEF3C5B71C9A1426AD5F48D - -Count = 1073 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BD4185160F5ED88930E22F46AF414BEA1 - -Count = 1074 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B0F97287F1535F1C3ADFB5FC55BC05AE3 - -Count = 1075 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BC77433961DC9C3B9921DEA7D023C0767 - -Count = 1076 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B34CFD3A806C74A813388F8AD3FF4F8C7 - -Count = 1077 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B654F40A547EE69F11409332357B700AE - -Count = 1078 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B377F930C72384B3D79130E741BE305AB - -Count = 1079 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B32B1EE63CCF39EBAAAF1E9845EC03428 - -Count = 1080 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B1A47B2427EC1F133ADB296F8D74276B7 - -Count = 1081 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F1011121314151617 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B78EDCD520DAEE34C59B7C6E11F9A55D9 - -Count = 1082 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B3060CD6C0CCCDF5A83DFE4685E31647D - -Count = 1083 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BFF42E4A548BDACDBE4E16DBB5F157BE2 - -Count = 1084 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B8EBA7874CCB6A35CFE446E6873FD3F57 - -Count = 1085 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BB7F91EDF1876D69F3CF663F10A38AC79 - -Count = 1086 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B8727CADBED5E9BAA865DA045778855C0 - -Count = 1087 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDF5C64BF14085D85889697478759587F - -Count = 1088 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BE9A219A89846E6396DDE3AF29F0425DE - -Count = 1089 -Key = 000102030405060708090A0B0C0D0E0F -Nonce = 000102030405060708090A0B -PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B76604A0135D48F2C59D38E2B0072703F - +Count = 1 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = +CT = F15ACBDAAD35B3172B71A67F6D61743E + +Count = 2 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00 +CT = 34A51A359BB2BC6E0FD2FE971A8F2E9A + +Count = 3 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001 +CT = F1B7119EE3E759F50B23D20CC34F3BD2 + +Count = 4 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102 +CT = 68668A3627C7D4FCE5DB770CFDE3B4C6 + +Count = 5 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203 +CT = 65B32A1FF4548BD6C3E880D1F8D29832 + +Count = 6 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304 +CT = 89AEEE9C5A7E3377C3EF1623AC8C18BE + +Count = 7 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405 +CT = F06E6E2DCCAC2B1BE87AA1694A954B85 + +Count = 8 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506 +CT = 7CDE5DB1EACAAE1AED428BB7DA7346A2 + +Count = 9 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 0001020304050607 +CT = 3EF470DA12441DE00B4AF48B299DB5EF + +Count = 10 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708 +CT = 6687F92C696A4E9DA87EA41DAA51081D + +Count = 11 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 00010203040506070809 +CT = CAE0E7766CAEB7E14A8238415E21C48B + +Count = 12 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A +CT = F86A1C0AD98EADBDCA619A3419A6F380 + +Count = 13 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B +CT = 1A27A16634EA15F59B8FBB62CB06BDBC + +Count = 14 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C +CT = B7297B7DB06F6F4DDE9AE6AC0C8302E5 + +Count = 15 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D +CT = B25A050247EE077E52117FEEA4B955E3 + +Count = 16 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E +CT = 360B5CB0CCC1914211DFD65EF1B1F3EF + +Count = 17 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F +CT = F8D62F1384C3258A6E3483766F70B9C3 + +Count = 18 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 2359560C641B5CDACDED28D9C0A45D81 + +Count = 19 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = EBBA4DE56CE76EA0F20B9D6199580005 + +Count = 20 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 1801ADDB77E9E798539E8FB1A490FFA5 + +Count = 21 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 49813ED636C0C4E8741F443FCCD307CC + +Count = 22 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 1BB1ED7F0316E62419057968808702C9 + +Count = 23 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 1E7F9010BDDD33A3CAE79E98C5A4334A + +Count = 24 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 3689CC310FEF5C2ACDA4E1E44C2671D5 + +Count = 25 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 5423B3217C804E5539A1B1FD84FE52BB + +Count = 26 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 1CAEB31F7DE27243E3C99374C555631F + +Count = 27 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = D38C9AD6399301C284F71AA7C4717C80 + +Count = 28 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = A2740607BD980E459E521974E8993835 + +Count = 29 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 9B3760AC69587B865CE014ED915CAB1B + +Count = 30 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = ABE9B4A89C7036B3E64BD759ECEC52A2 + +Count = 31 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = F3921ACC6526F09CE880E05B1C3D5F1D + +Count = 32 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = C56C67DBE9684B200DC84DEE046022BC + +Count = 33 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 5AAE347244FA223539C5F9379B16775D + +Count = 34 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = +CT = 75F797289653F5E1F298E281E32386CFCC + +Count = 35 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00 +CT = 753268F9796572EE8BBC41D90B54689568 + +Count = 36 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001 +CT = 75F77AF2D21D270B10B8B0F5908DA88020 + +Count = 37 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102 +CT = 756EAB697AD907861956485090B3040F34 + +Count = 38 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203 +CT = 75637EC9530A94D933707BA74DB63523C0 + +Count = 39 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304 +CT = 758F630DD0A4BE6192707C31BFE26BA34C + +Count = 40 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405 +CT = 75F6A38D61326C79FE5BE986F50472F077 + +Count = 41 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506 +CT = 757A13BEFD140AFCFF5ED1AC2B9494FD50 + +Count = 42 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 0001020304050607 +CT = 7538399396EC844F05B8D9D317677A0E1D + +Count = 43 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708 +CT = 75604A1A6097AA1C781BED8381E4B6B3EF + +Count = 44 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 00010203040506070809 +CT = 75CC2D043A926EE504F9111FDD10C67F79 + +Count = 45 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A +CT = 75FEA7FF46274EFF5879F2BDA857414872 + +Count = 46 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B +CT = 751CEA422ACA2A4710281C9CFE85E1064E + +Count = 47 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C +CT = 75B1E498314EAF3DA86D09C1304264B917 + +Count = 48 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D +CT = 75B497E64EB92E559BE1825872EA5EEE11 + +Count = 49 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E +CT = 7530C6BFFC3201C3A7A24CF1C2BF56481D + +Count = 50 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75FE1BCC5F7A03776FDDA7A4EA21970231 + +Count = 51 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 752594B5409ADB0E3F7E7E0F458E43E673 + +Count = 52 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75ED77AEA992273C454198BAFDD7BFBBF7 + +Count = 53 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 751ECC4E978929B57DE00DA82DEA774457 + +Count = 54 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 754F4CDD9AC800960DC78C63A38234BC3E + +Count = 55 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 751D7C0E33FDD6B4C1AA965EF4CE60B93B + +Count = 56 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 7518B2735C431D61467974B9048B4388B8 + +Count = 57 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 7530442F7DF12F0ECF7E37C67802C1CA27 + +Count = 58 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 7552EE506D82401CB08A329661CA19E949 + +Count = 59 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 751A635053832220A6505AB4E88BB2D8ED + +Count = 60 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75D541799AC753532737643D3B8A96C772 + +Count = 61 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75A4B9E54B43585CA02DC13EE8A67E83C7 + +Count = 62 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 759DFA83E097982963EF733371DFBB10E9 + +Count = 63 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75AD2457E462B0645655D8F0C5A20BE950 + +Count = 64 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F55FF9809BE6A2795B13C7C752DAE4EF + +Count = 65 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75C3A1849717A819C5BE5B6A724A87994E + +Count = 66 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 755C63D73EBA3A70D08A56DEABD5F1CCAF + +Count = 67 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = +CT = 75F8800643012C02E88E68F12495367A7CBF + +Count = 68 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00 +CT = 75F845F992EE1A85E7F74C527C7D4194261B + +Count = 69 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001 +CT = 75F880EB994562D0026C48A350E698543353 + +Count = 70 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102 +CT = 75F8193A02EDA6F08F65A65BF5E6A6F8BC47 + +Count = 71 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203 +CT = 75F814EFA2C47563D04F8068023BA3C990B3 + +Count = 72 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304 +CT = 75F8F8F26647DB4968EE806F94C9F797103F + +Count = 73 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405 +CT = 75F88132E6F64D9B7082ABFA2383118E4304 + +Count = 74 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506 +CT = 75F80D82D56A6BFDF583AEC2095D81684E23 + +Count = 75 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 0001020304050607 +CT = 75F84FA8F8019373467948CA76617286BD6E + +Count = 76 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708 +CT = 75F817DB71F7E85D1504EBFE26F7F14A009C + +Count = 77 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 00010203040506070809 +CT = 75F8BBBC6FADED99EC780902BAAB053ACC0A + +Count = 78 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A +CT = 75F8893694D158B9F62489E118DE42BDFB01 + +Count = 79 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B +CT = 75F86B7B29BDB5DD4E6CD80F3988901DB53D + +Count = 80 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C +CT = 75F8C675F3A6315834D49D1A644657980A64 + +Count = 81 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D +CT = 75F8C3068DD9C6D95CE71191FD04FFA25D62 + +Count = 82 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E +CT = 75F84757D46B4DF6CADB525F54B4AAAAFB6E + +Count = 83 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8898AA7C805F47E132DB4019C346BB142 + +Count = 84 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F85205DED7E52C07438E6DAA339BBF5500 + +Count = 85 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F89AE6C53EEDD03539B18B1F8BC2430884 + +Count = 86 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8695D2500F6DEBC01101E0D5BFF8BF724 + +Count = 87 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F838DDB60DB7F79F71379FC6D597C80F4D + +Count = 88 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F86AED65A48221BDBD5A85FB82DB9C0A48 + +Count = 89 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F86F2318CB3CEA683A89671C729EBF3BCB + +Count = 90 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F847D544EA8ED807B38E24630E173D7954 + +Count = 91 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8257F3BFAFDB715CC7A213317DFE55A3A + +Count = 92 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F86DF23BC4FCD529DAA049119E9E4E6B9E + +Count = 93 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8A2D0120DB8A45A5BC777984D9F6A7401 + +Count = 94 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8D3288EDC3CAF55DCDDD29B9EB38230B4 + +Count = 95 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8EA6BE877E86F201F1F609607CA47A39A + +Count = 96 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8DAB53C731D476D2AA5CB55B3B7F75A23 + +Count = 97 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F882CE9217E411AB05AB0062B14726579C + +Count = 98 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8B430EF00685F10B94E48CF045F7B2A3D + +Count = 99 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F82BF2BCA9C5CD79AC7A457BDDC00D7FDC + +Count = 100 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = +CT = 75F8BD3516DE07D6044CA2EDC2B2770E1DA70A + +Count = 101 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00 +CT = 75F8BDF0E90FE8E08343DBC961EA9F79F3FDAE + +Count = 102 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001 +CT = 75F8BD35FB044398D6A640CD90C604A033E8E6 + +Count = 103 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102 +CT = 75F8BDAC2A9FEB5CF62B49236863049E9F67F2 + +Count = 104 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203 +CT = 75F8BDA1FF3FC28F657463055B94D99BAE4B06 + +Count = 105 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304 +CT = 75F8BD4DE2FB41214FCCC2055C022BCFF0CB8A + +Count = 106 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405 +CT = 75F8BD34227BF0B79DD4AE2EC9B56129E998B1 + +Count = 107 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506 +CT = 75F8BDB892486C91FB51AF2BF19FBFB90F9596 + +Count = 108 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 0001020304050607 +CT = 75F8BDFAB865076975E255CDF9E0834AE166DB + +Count = 109 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708 +CT = 75F8BDA2CBECF1125BB1286ECDB015C92DDB29 + +Count = 110 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 00010203040506070809 +CT = 75F8BD0EACF2AB179F48548C312C493D5D17BF + +Count = 111 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A +CT = 75F8BD3C2609D7A2BF52080CD28E3C7ADA20B4 + +Count = 112 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B +CT = 75F8BDDE6BB4BB4FDBEA405D3CAF6AA87A6E88 + +Count = 113 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C +CT = 75F8BD73656EA0CB5E90F81829F2A46FFFD1D1 + +Count = 114 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD761610DF3CDFF8CB94A26BE6C7C586D7 + +Count = 115 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BDF247496DB7F06EF7D76CC25692CD20DB + +Count = 116 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD3C9A3ACEFFF2DA3FA887977E0C0C6AF7 + +Count = 117 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BDE71543D11F2AA36F0B5E3CD1A3D88EB5 + +Count = 118 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD2FF6583817D6911534B88969FA24D331 + +Count = 119 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BDDC4DB8060CD8182D952D9BB9C7EC2C91 + +Count = 120 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD8DCD2B0B4DF13B5DB2AC5037AFAFD4F8 + +Count = 121 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BDDFFDF8A278271991DFB66D60E3FBD1FD + +Count = 122 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BDDA3385CDC6ECCC160C548A90A6D8E07E + +Count = 123 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BDF2C5D9EC74DEA39F0B17F5EC2F5AA2E1 + +Count = 124 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD906FA6FC07B1B1E0FF12A5F5E782818F + +Count = 125 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BDD8E2A6C206D38DF6257A877CA629B02B + +Count = 126 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD17C08F0B42A2FE7742440EAFA70DAFB4 + +Count = 127 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD663813DAC6A9F1F058E10D7C8BE5EB01 + +Count = 128 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD5F7B7571126984339A5300E5F220782F + +Count = 129 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD6FA5A175E741C90620F8C3518F908196 + +Count = 130 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD37DE0F111E170F292E33F4537F418C29 + +Count = 131 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD012072069259B495CB7B59E6671CF188 + +Count = 132 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD9EE221AF3FCBDD80FF76ED3FF86AA469 + +Count = 133 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = +CT = 75F8BD7F52BDA7B96A4B5D488D71E517A1DC1495 + +Count = 134 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00 +CT = 75F8BD7F974276565CCC5231A9D2BDFFD6324E31 + +Count = 135 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001 +CT = 75F8BD7F52507DFD2499B7AAAD2391640FF25B79 + +Count = 136 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102 +CT = 75F8BD7FCB81E655E0B93AA343DB3464315ED46D + +Count = 137 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203 +CT = 75F8BD7FC654467C332A658965E8C3B9346FF899 + +Count = 138 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304 +CT = 75F8BD7F2A4982FF9D00DD2865EF554B60317815 + +Count = 139 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405 +CT = 75F8BD7F5389024E0BD2C5444E7AE20186282B2E + +Count = 140 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506 +CT = 75F8BD7FDF3931D22DB440454B42C8DF16CE2609 + +Count = 141 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 0001020304050607 +CT = 75F8BD7F9D131CB9D53AF3BFAD4AB7E3E520D544 + +Count = 142 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708 +CT = 75F8BD7FC560954FAE14A0C20E7EE77566EC68B6 + +Count = 143 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 00010203040506070809 +CT = 75F8BD7F69078B15ABD059BEEC827B29929CA420 + +Count = 144 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A +CT = 75F8BD7F5B8D70691EF043E26C61D95CD51B932B + +Count = 145 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B +CT = 75F8BD7FB9C0CD05F394FBAA3D8FF80A07BBDD17 + +Count = 146 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F14CE171E77118112789AA5C4C03E624E + +Count = 147 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F11BD69618090E921F4113C8668043548 + +Count = 148 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F95EC30D30BBF7F1DB7DF95363D0C9344 + +Count = 149 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F5B31437043BDCBD5C834C01EA3CDD968 + +Count = 150 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F80BE3A6FA365B2856BED6BB10C193D2A + +Count = 151 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F485D2186AB9980FF540BDE0955E560AE + +Count = 152 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7FBBE6C1B8B09709C7F59ECCD9682D9F0E + +Count = 153 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7FEA6652B5F1BE2AB7D21F0757006E6767 + +Count = 154 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7FB856811CC468087BBF053A004C3A6262 + +Count = 155 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7FBD98FC737AA3DDFC6CE7DDF0091953E1 + +Count = 156 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F956EA052C891B2756BA4A28C809B117E + +Count = 157 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7FF7C4DF42BBFEA00A9FA1F29548433210 + +Count = 158 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7FBF49DF7CBA9C9C1C45C9D01C09E803B4 + +Count = 159 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F706BF6B5FEEDEF9D22F759CF08CC1C2B + +Count = 160 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F01936A647AE6E01A38525A1C2424589E + +Count = 161 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F38D00CCFAE2695D9FAE057855DE1CBB0 + +Count = 162 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F080ED8CB5B0ED8EC404B943120513209 + +Count = 163 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F507576AFA2581EC34E80A333D0803FB6 + +Count = 164 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F668B0BB82E16A57FABC80E86C8DD4217 + +Count = 165 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7FF94958118384CC6A9FC5BA5F57AB17F6 + +Count = 166 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = +CT = 75F8BD7F4713632EDC7CD5ADE3F56280918D754F0F + +Count = 167 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00 +CT = 75F8BD7F47D69CFF334A52A29AD1C1D879FA9B15AB + +Count = 168 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001 +CT = 75F8BD7F47138EF49832074701D530F4E2235B00E3 + +Count = 169 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102 +CT = 75F8BD7F478A5F6F30F627CA083BC851E21DF78FF7 + +Count = 170 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203 +CT = 75F8BD7F47878ACF1925B495221DFBA63F18C6A303 + +Count = 171 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304 +CT = 75F8BD7F476B970B9A8B9E2D831DFC30CD4C98238F + +Count = 172 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405 +CT = 75F8BD7F4712578B2B1D4C35EF36698787AA8170B4 + +Count = 173 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506 +CT = 75F8BD7F479EE7B8B73B2AB0EE3351AD593A677D93 + +Count = 174 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 0001020304050607 +CT = 75F8BD7F47DCCD95DCC3A40314D559D265C9898EDE + +Count = 175 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708 +CT = 75F8BD7F4784BE1C2AB88A5069766D82F34A45332C + +Count = 176 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 00010203040506070809 +CT = 75F8BD7F4728D90270BD4EA91594911EAFBE35FFBA + +Count = 177 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A +CT = 75F8BD7F471A53F90C086EB3491472BCDAF9B2C8B1 + +Count = 178 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B +CT = 75F8BD7F47F81E4460E50A0B01459C9D8C2B12868D + +Count = 179 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4755109E7B618F71B90089C042EC9739D4 + +Count = 180 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F475063E004960E198A8C02590044AD6ED2 + +Count = 181 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F47D432B9B61D218FB6CFCCF0B011A5C8DE + +Count = 182 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F471AEFCA1555233B7EB027A5988F6482F2 + +Count = 183 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F47C160B30AB5FB422E13FE0E3720B066B0 + +Count = 184 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F470983A8E3BD0770542C18BB8F794C3B34 + +Count = 185 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F47FA3848DDA609F96C8D8DA95F4484C494 + +Count = 186 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F47ABB8DBD0E720DA1CAA0C62D12CC73CFD + +Count = 187 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F47F9880879D2F6F8D0C7165F86609339F8 + +Count = 188 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F47FC4675166C3D2D5714F4B87625B0087B + +Count = 189 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F47D4B02937DE0F42DE13B7C70AAC324AE4 + +Count = 190 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F47B61A5627AD6050A1E7B2971364EA698A + +Count = 191 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F47FE975619AC026CB73DDAB59A2541582E + +Count = 192 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4731B57FD0E8731F365AE43C49246547B1 + +Count = 193 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F47404DE3016C7810B140413F9A088D0304 + +Count = 194 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F47790E85AAB8B8657282F332037148902A + +Count = 195 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4749D051AE4D9028473858F1B70CF86993 + +Count = 196 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4711ABFFCAB4C6EE683693C6B5FC29642C + +Count = 197 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F47275582DD388855D4D3DB6B00E474198D + +Count = 198 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F47B897D174951A3CC1E7D6DFD97B024C6C + +Count = 199 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = +CT = 75F8BD7F4702B4A392153FB14CC7B698E976C1B4204A + +Count = 200 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00 +CT = 75F8BD7F4702715C43FA093643BE923BB19EB65A7AEE + +Count = 201 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001 +CT = 75F8BD7F4702B44E48517163A62596CA9D056F9A6FA6 + +Count = 202 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102 +CT = 75F8BD7F47022D9FD3F9B5432B2C783238055136E0B2 + +Count = 203 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203 +CT = 75F8BD7F4702204A73D066D074065E01CFD85407CC46 + +Count = 204 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304 +CT = 75F8BD7F4702CC57B753C8FACCA75E06592A00594CCA + +Count = 205 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405 +CT = 75F8BD7F4702B59737E25E28D4CB7593EE60E6401FF1 + +Count = 206 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506 +CT = 75F8BD7F47023927047E784E51CA70ABC4BE76A612D6 + +Count = 207 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 0001020304050607 +CT = 75F8BD7F47027B0D291580C0E23096A3BB828548E19B + +Count = 208 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708 +CT = 75F8BD7F4702237EA0E3FBEEB14D3597EB1406845C69 + +Count = 209 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 00010203040506070809 +CT = 75F8BD7F47028F19BEB9FE2A4831D76B7748F2F490FF + +Count = 210 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A +CT = 75F8BD7F4702BD9345C54B0A526D5788D53DB573A7F4 + +Count = 211 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B +CT = 75F8BD7F47025FDEF8A9A66EEA250666F46B67D3E9C8 + +Count = 212 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702F2D022B222EB909D4373A9A5A0565691 + +Count = 213 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702F7A35CCDD56AF8AECFF830E7086C0197 + +Count = 214 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F470273F2057F5E456E928C3699575D64A79B + +Count = 215 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702BD2F76DC1647DA5AF3DDCC7FC3A5EDB7 + +Count = 216 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F470266A00FC3F69FA30A500467D06C7109F5 + +Count = 217 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702AE43142AFE6391706FE2D268358D5471 + +Count = 218 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F47025DF8F414E56D1848CE77C0B80845ABD1 + +Count = 219 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F47020C786719A4443B38E9F60B36600653B8 + +Count = 220 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F47025E48B4B0919219F484EC36612C5256BD + +Count = 221 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F47025B86C9DF2F59CC73570ED1916971673E + +Count = 222 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702737095FE9D6BA3FA504DAEEDE0F325A1 + +Count = 223 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F470211DAEAEEEE04B185A448FEF4282B06CF + +Count = 224 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F47025957EAD0EF668D937E20DC7D6980376B + +Count = 225 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F47029675C319AB17FE12191E55AE68A428F4 + +Count = 226 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702E78D5FC82F1CF19503BB567D444C6C41 + +Count = 227 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702DECE3963FBDC8456C1095BE43D89FF6F + +Count = 228 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EE10ED670EF4C9637BA29850403906D6 + +Count = 229 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702B66B4303F7A20F4C7569AF52B0E80B69 + +Count = 230 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F470280953E147BECB4F0902102E7A8B576C8 + +Count = 231 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F47021F576DBDD67EDDE5A42CB63E37C32329 + +Count = 232 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = +CT = 75F8BD7F4702EA437F55891181F70BDE51D1422E2BA8FE + +Count = 233 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00 +CT = 75F8BD7F4702EA868084662706F872FAF289AA59C5F25A + +Count = 234 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001 +CT = 75F8BD7F4702EA43928FCD5F531DE9FE03A5318005E712 + +Count = 235 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102 +CT = 75F8BD7F4702EADA4314659B7390E010FB0031BEA96806 + +Count = 236 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203 +CT = 75F8BD7F4702EAD796B44C48E0CFCA36C8F7ECBB9844F2 + +Count = 237 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304 +CT = 75F8BD7F4702EA3B8B70CFE6CA776B36CF611EEFC6C47E + +Count = 238 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405 +CT = 75F8BD7F4702EA424BF07E70186F071D5AD65409DF9745 + +Count = 239 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506 +CT = 75F8BD7F4702EACEFBC3E2567EEA061862FC8A99399A62 + +Count = 240 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 0001020304050607 +CT = 75F8BD7F4702EA8CD1EE89AEF059FCFE6A83B66AD7692F + +Count = 241 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708 +CT = 75F8BD7F4702EAD4A2677FD5DE0A815D5ED320E91BD4DD + +Count = 242 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA78C57925D01AF3FDBFA24F7C1D6B184B + +Count = 243 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA4A4F8259653AE9A13F41ED095AEC2F40 + +Count = 244 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EAA8023F35885E51E96EAFCC5F884C617C + +Count = 245 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA050CE52E0CDB2B512BBA91914FC9DE25 + +Count = 246 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA007F9B51FB5A4362A73108D3E7F38923 + +Count = 247 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA842EC2E37075D55EE4FFA163B2FB2F2F + +Count = 248 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA4AF3B140387761969B14F44B2C3A6503 + +Count = 249 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA917CC85FD8AF18C638CD5FE483EE8141 + +Count = 250 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA599FD3B6D0532ABC072BEA5CDA12DCC5 + +Count = 251 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EAAA243388CB5DA384A6BEF88CE7DA2365 + +Count = 252 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EAFBA4A0858A7480F4813F33028F99DB0C + +Count = 253 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EAA994732CBFA2A238EC250E55C3CDDE09 + +Count = 254 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EAAC5A0E43016977BF3FC7E9A586EEEF8A + +Count = 255 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA84AC5262B35B1836388496D90F6CAD15 + +Count = 256 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EAE6062D72C0340A49CC81C6C0C7B48E7B + +Count = 257 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EAAE8B2D4CC156365F16E9E449861FBFDF + +Count = 258 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA61A90485852745DE71D76D9A873BA040 + +Count = 259 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA10519854012C4A596B726E49ABD3E4F5 + +Count = 260 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA2912FEFFD5EC3F9AA9C063D0D21677DB + +Count = 261 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA19CC2AFB20C472AF136BA064AFA68E62 + +Count = 262 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA41B7849FD992B4801DA097665F7783DD + +Count = 263 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA7749F98855DC0F3CF8E83AD3472AFE7C + +Count = 264 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EAE88BAA21F84E6629CCE58E0AD85CAB9D + +Count = 265 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = +CT = 75F8BD7F4702EA536D5F65A0813549A46484341041EB4E4D + +Count = 266 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00 +CT = 75F8BD7F4702EA53A8A0B44FB7B246DD40276CF8360514E9 + +Count = 267 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001 +CT = 75F8BD7F4702EA536DB2BFE4CFE7A34644D64063EFC501A1 + +Count = 268 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102 +CT = 75F8BD7F4702EA53F463244C0BC72E4FAA2EE563D1698EB5 + +Count = 269 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203 +CT = 75F8BD7F4702EA53F9B68465D85471658C1D12BED458A241 + +Count = 270 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304 +CT = 75F8BD7F4702EA5315AB40E6767EC9C48C1A844C800622CD + +Count = 271 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405 +CT = 75F8BD7F4702EA536C6BC057E0ACD1A8A78F3306661F71F6 + +Count = 272 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506 +CT = 75F8BD7F4702EA53E0DBF3CBC6CA54A9A2B719D8F6F97CD1 + +Count = 273 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 0001020304050607 +CT = 75F8BD7F4702EA53A2F1DEA03E44E75344BF66E405178F9C + +Count = 274 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708 +CT = 75F8BD7F4702EA53FA825756456AB42EE78B367286DB326E + +Count = 275 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA5356E5490C40AE4D520577AA2E72ABFEF8 + +Count = 276 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA53646FB270F58E570E8594085B352CC9F3 + +Count = 277 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA5386220F1C18EAEF46D47A290DE78C87CF + +Count = 278 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA532B2CD5079C6F95FE916F74C320093896 + +Count = 279 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA532E5FAB786BEEFDCD1DE4ED8188336F90 + +Count = 280 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA53AA0EF2CAE0C16BF15E2A4431DD3BC99C + +Count = 281 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA5364D38169A8C3DF3921C1111943FA83B0 + +Count = 282 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA53BF5CF876481BA6698218BAB6EC2E67F2 + +Count = 283 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA5377BFE39F40E79413BDFE0F0EB5D23A76 + +Count = 284 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA53840403A15BE91D2B1C6B1DDE881AC5D6 + +Count = 285 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA53D58490AC1AC03E5B3BEAD650E0593DBF + +Count = 286 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA5387B443052F161C9756F0EB07AC0D38BA + +Count = 287 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA53827A3E6A91DDC91085120CF7E92E0939 + +Count = 288 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA53AA8C624B23EFA6998251738B60AC4BA6 + +Count = 289 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA53C8261D5B5080B4E676542392A87468C8 + +Count = 290 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA5380AB1D6551E288F0AC3C011BE9DF596C + +Count = 291 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA534F8934AC1593FB71CB0288C8E8FB46F3 + +Count = 292 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA533E71A87D9198F4F6D1A78B1BC4130246 + +Count = 293 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA530732CED64558813513158682BDD69168 + +Count = 294 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA5337EC1AD2B070CC00A9BE4536C06668D1 + +Count = 295 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA536F97B4B649260A2FA775723430B7656E + +Count = 296 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535969C9A1C568B193423DDF8128EA18CF + +Count = 297 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 0001020304050607 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA53C6AB9A0868FAD88676306B58B79C4D2E + +Count = 298 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = +CT = 75F8BD7F4702EA535ACD2EE4E235206302B93720871498261B + +Count = 299 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00 +CT = 75F8BD7F4702EA535A08D1350D03A76C7B9D94786F63767CBF + +Count = 300 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001 +CT = 75F8BD7F4702EA535ACDC33EA67BF289E0996554F4BAB669F7 + +Count = 301 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102 +CT = 75F8BD7F4702EA535A5412A50EBFD204E9779DF1F4841AE6E3 + +Count = 302 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203 +CT = 75F8BD7F4702EA535A59C705276C415BC351AE0629812BCA17 + +Count = 303 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304 +CT = 75F8BD7F4702EA535AB5DAC1A4C26BE36251A990DBD5754A9B + +Count = 304 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405 +CT = 75F8BD7F4702EA535ACC1A411554B9FB0E7A3C2791336C19A0 + +Count = 305 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A40AA728972DF7E0F7F040D4FA38A1487 + +Count = 306 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A02805FE28A51CDF5990C72735064E7CA + +Count = 307 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A5AF3D614F17F9E883A3822E5D3A85A38 + +Count = 308 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535AF694C84EF4BB67F4D8C4BEB927D896AE + +Count = 309 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535AC41E3332419B7DA858271CCC605FA1A5 + +Count = 310 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A26538E5EACFFC5E009C93D9AB2FFEF99 + +Count = 311 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A8B5D5445287ABF584CDC6054757A50C0 + +Count = 312 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A8E2E2A3ADFFBD76BC057F916DD4007C6 + +Count = 313 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A0A7F738854D44157839950A68848A1CA + +Count = 314 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535AC4A2002B1CD6F59FFC72058E1689EBE6 + +Count = 315 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1F2D7934FC0E8CCF5FABAE21B95D0FA4 + +Count = 316 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535AD7CE62DDF4F2BEB5604D1B99E0A15220 + +Count = 317 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A247582E3EFFC378DC1D80949DD69AD80 + +Count = 318 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A75F511EEAED514FDE659C2C7B52A55E9 + +Count = 319 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A27C5C2479B0336318B43FF90F97E50EC + +Count = 320 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A220BBF2825C8E3B658A11860BC5D616F + +Count = 321 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A0AFDE30997FA8C3F5FE2671C35DF23F0 + +Count = 322 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A68579C19E4959E40ABE73705FD07009E + +Count = 323 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A20DA9C27E5F7A256718F158CBCAC313A + +Count = 324 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535AEFF8B5EEA186D1D716B19C5FBD882EA5 + +Count = 325 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A9E00293F258DDE500C149F8C91606A10 + +Count = 326 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535AA7434F94F14DAB93CEA69215E8A5F93E + +Count = 327 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A979D9B900465E6A6740D51A195150087 + +Count = 328 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535ACFE635F4FD3320897AC666A365C40D38 + +Count = 329 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535AF91848E3717D9B359F8ECB167D997099 + +Count = 330 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A66DA1B4ADCEFF220AB837FCFE2EF2578 + +Count = 331 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = +CT = 75F8BD7F4702EA535A1C305CBEF8FDC04C6B24F5314FEE4BB14E + +Count = 332 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00 +CT = 75F8BD7F4702EA535A1CF5A36F17CB474312005669A799A5EBEA + +Count = 333 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001 +CT = 75F8BD7F4702EA535A1C30B164BCB312A68904A7453C4065FEA2 + +Count = 334 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102 +CT = 75F8BD7F4702EA535A1CA960FF1477322B80EA5FE03C7EC971B6 + +Count = 335 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CA4B55F3DA4A174AACC6C17E17BF85D42 + +Count = 336 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1C48A89BBE0A8BCC0BCC6B81132FA6DDCE + +Count = 337 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1C31681B0F9C59D467E7FE3659C9BF8EF5 + +Count = 338 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CBDD82893BA3F5166E2C61C87595983D2 + +Count = 339 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CFFF205F842B1E29C04CE63BBAAB7709F + +Count = 340 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CA7818C0E399FB1E1A7FA332D297BCD6D + +Count = 341 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1C0BE692543C5B489D4506AF71DD0B01FB + +Count = 342 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1C396C6928897B52C1C5E50D049A8C36F0 + +Count = 343 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CDB21D444641FEA89940B2C52482C78CC + +Count = 344 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1C762F0E5FE09A9031D11E719C8FA9C795 + +Count = 345 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1C735C7020171BF8025D95E8DE27939093 + +Count = 346 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CF70D29929C346E3E1E5B416E729B369F + +Count = 347 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1C39D05A31D436DAF661B01446EC5A7CB3 + +Count = 348 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE25F232E34EEA3A6C269BFE9438E98F1 + +Count = 349 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1C2ABC38C73C1291DCFD8F0A511A72C575 + +Count = 350 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CD907D8F9271C18E45C1A188127BA3AD5 + +Count = 351 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1C88874BF466353B947B9BD30F4FF9C2BC + +Count = 352 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CDAB7985D53E319581681EE5803ADC7B9 + +Count = 353 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CDF79E532ED28CCDFC56309A8468EF63A + +Count = 354 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CF78FB9135F1AA356C22076D4CF0CB4A5 + +Count = 355 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1C9525C6032C75B129362526CD07D497CB + +Count = 356 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CDDA8C63D2D178D3FEC4D0444467FA66F + +Count = 357 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1C128AEFF46966FEBE8B738D97475BB9F0 + +Count = 358 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1C63727325ED6DF13991D68E446BB3FD45 + +Count = 359 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1C5A31158E39AD84FA536483DD12766E6B + +Count = 360 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1C6AEFC18ACC85C9CFE9CF40696FC697D2 + +Count = 361 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1C32946FEE35D30FE0E704776B9F179A6D + +Count = 362 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1C046A12F9B99DB45C024CDADE874AE7CC + +Count = 363 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 00010203040506070809 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1C9BA84150140FDD4936416E07183CB22D + +Count = 364 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = +CT = 75F8BD7F4702EA535A1CE25C0A2BEADD549AF1B448FE28B6A4CC36 + +Count = 365 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00 +CT = 75F8BD7F4702EA535A1CE299F5FA05EBD3958890EBA6C0C14A9692 + +Count = 366 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001 +CT = 75F8BD7F4702EA535A1CE25CE7F1AE93867013941A8A5B188A83DA + +Count = 367 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102 +CT = 75F8BD7F4702EA535A1CE2C5366A0657A6FD1A7AE22F5B26260CCE + +Count = 368 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE2C8E3CA2F8435A2305CD1D8862317203A + +Count = 369 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE224FE0EAC2A1F1A915CD64E747749A0B6 + +Count = 370 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE25D3E8E1DBCCD02FD7743F93E9150F38D + +Count = 371 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE2D18EBD819AAB87FC727BD3E001B6FEAA + +Count = 372 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE293A490EA622534069473ACDCF2580DE7 + +Count = 373 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE2CBD7191C190B677B3747FC4A7194B015 + +Count = 374 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE267B007461CCF9E07D5BB601685E47C83 + +Count = 375 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE2553AFC3AA9EF845B5558C263C2634B88 + +Count = 376 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE2B7774156448B3C1304B6E33510C305B4 + +Count = 377 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE21A799B4DC00E46AB41A3BEFBD746BAED + +Count = 378 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE21F0AE532378F2E98CD2827B97F7CEDEB + +Count = 379 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE29B5BBC80BCA0B8A48EE68E092A744BE7 + +Count = 380 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE25586CF23F4A20C6CF10DDB21B4B501CB + +Count = 381 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE28E09B63C147A753C52D4708E1B61E589 + +Count = 382 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE246EAADD51C8647466D32C536429DB80D + +Count = 383 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE2B5514DEB0788CE7ECCA7D7E67F5547AD + +Count = 384 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE2E4D1DEE646A1ED0EEB261C681716BFC4 + +Count = 385 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE2B6E10D4F7377CFC2863C213F5B42BAC1 + +Count = 386 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE2B32F7020CDBC1A4555DEC6CF1E618B42 + +Count = 387 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE29BD92C017F8E75CC529DB9B397E3C9DD + +Count = 388 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE2F97353110CE167B3A698E9AA5F3BEAB3 + +Count = 389 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE2B1FE532F0D835BA57CF0CB231E90DB17 + +Count = 390 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE27EDC7AE649F228241BCE42F01FB4C488 + +Count = 391 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE20F24E637CDF927A3016B4123335C803D + +Count = 392 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23667809C19395260C3D94CBA4A991313 + +Count = 393 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE206B95498EC111F5579728F0E3729EAAA + +Count = 394 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE25EC2FAFC1547D97A77B9B80CC7F8E715 + +Count = 395 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE2683C87EB990962C692F115B9DFA59AB4 + +Count = 396 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE2F7FED442349B0BD3A6FCA16040D3CF55 + +Count = 397 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = +CT = 75F8BD7F4702EA535A1CE23E2667F4CAD2004ABC625DDA08BF849DA7 + +Count = 398 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00 +CT = 75F8BD7F4702EA535A1CE23EE3982525E48745C546FE82E0C86AC703 + +Count = 399 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E268A2E8E9CD2A05E420FAE7B11AAD24B + +Count = 400 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23EBF5BB52658F22D57ACF70B7B2F065D5F + +Count = 401 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23EB28E150F8B61727D8AC4FCA62A3771AB + +Count = 402 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E5E93D18C254BCADC8AC36A547E69F127 + +Count = 403 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2753513DB399D2B0A156DD1E9870A21C + +Count = 404 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23EABE362A195FF57B1A46EF7C00896AF3B + +Count = 405 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23EE9C94FCA6D71E44B426688FCFB785C76 + +Count = 406 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23EB1BAC63C165FB736E152D86A78B4E184 + +Count = 407 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E1DDDD866139B4E4A03AE44368CC42D12 + +Count = 408 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2F57231AA6BB5416834DE643CB431A19 + +Count = 409 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23ECD1A9E764BDFEC5ED2A3C71519E35425 + +Count = 410 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E6014446DCF5A96E697B69ADBDE66EB7C + +Count = 411 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E65673A1238DBFED51B3D0399765CBC7A + +Count = 412 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23EE13663A0B3F468E958F3AA2923541A76 + +Count = 413 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2FEB1003FBF6DC212718FF01BD95505A + +Count = 414 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23EF464691C1B2EA57184C154AE1241B418 + +Count = 415 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E3C8772F513D2970BBB27E1164BBDE99C + +Count = 416 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23ECF3C92CB08DC1E331AB2F3C67675163C + +Count = 417 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E9EBC01C649F53D433D3338481E36EE55 + +Count = 418 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23ECC8CD26F7C231F8F5029051F5262EB50 + +Count = 419 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23EC942AF00C2E8CA0883CBE2EF1741DAD3 + +Count = 420 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23EE1B4F32170DAA58184889D939EC3984C + +Count = 421 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E831E8C3103B5B7FE708DCD8A561BBB22 + +Count = 422 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23ECB938C0F02D78BE8AAE5EF0317B08A86 + +Count = 423 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E04B1A5C646A6F869CDDB66D016949519 + +Count = 424 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E75493917C2ADF7EED77E65033A7CD1AC + +Count = 425 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E4C0A5FBC166D822D15CC689A43B94282 + +Count = 426 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E7CD48BB8E345CF18AF67AB2E3E09BB3B + +Count = 427 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E24AF25DC1A130937A1AC9C2CCED8B684 + +Count = 428 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E125158CB965DB28B44E43199D685CB25 + +Count = 429 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E8D930B623BCFDB9E70E9854049F39EC4 + +Count = 430 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = +CT = 75F8BD7F4702EA535A1CE23E2DA4710F232426B4955579426D01DD9895 + +Count = 431 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D618EDECC12A1BBEC71DA1A857633C231 + +Count = 432 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2DA49CD5676AF45E77752B361EAFF3D779 + +Count = 433 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D3D4D4ECFAED4D37E9BD3931E915F586D + +Count = 434 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D3098EEE67D478C54BDE064C3946E7499 + +Count = 435 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2DDC852A65D36D34F5BDE7F231C030F415 + +Count = 436 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2DA545AAD445BF2C999672457B2629A72E + +Count = 437 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D29F5994863D9A998934A6FA5B6CFAA09 + +Count = 438 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D6BDFB4239B571A627542109945215944 + +Count = 439 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D33AC3DD5E079491FD676400FC6EDE4B6 + +Count = 440 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D9FCB238FE5BDB063348ADC53329D2820 + +Count = 441 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2DAD41D8F3509DAA3FB4697E26751A1F2B + +Count = 442 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D4F0C659FBDF91277E5875F70A7BA5117 + +Count = 443 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2DE202BF84397C68CFA09202BE603FEE4E + +Count = 444 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2DE771C1FBCEFD00FC2C199BFCC805B948 + +Count = 445 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D6320984945D296C06FD7324C9D0D1F44 + +Count = 446 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2DADFDEBEA0DD02208103C676403CC5568 + +Count = 447 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D767292F5ED085B58B3E5CCCBAC18B12A + +Count = 448 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2DBE91891CE5F469228C037973F5E4ECAE + +Count = 449 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D4D2A6922FEFAE01A2D966BA3C82C130E + +Count = 450 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D1CAAFA2FBFD3C36A0A17A02DA06FEB67 + +Count = 451 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D4E9A29868A05E1A6670D9D7AEC3BEE62 + +Count = 452 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D4B5454E934CE3421B4EF7A8AA918DFE1 + +Count = 453 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D63A208C886FC5BA8B3AC05F6209A9D7E + +Count = 454 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D010877D8F59349D747A955EFE842BE10 + +Count = 455 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D498577E6F4F175C19DC17766A9E98FB4 + +Count = 456 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D86A75E2FB0800640FAFFFEB5A8CD902B + +Count = 457 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2DF75FC2FE348B09C7E05AFD668425D49E + +Count = 458 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2DCE1CA455E04B7C0422E8F0FFFDE047B0 + +Count = 459 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2DFEC27051156331319843334B8050BE09 + +Count = 460 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2DA6B9DE35EC35F71E968804497081B3B6 + +Count = 461 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D9047A322607B4CA273C0A9FC68DCCE17 + +Count = 462 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D0F85F08BCDE925B747CD1D25F7AA9BF6 + +Count = 463 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = +CT = 75F8BD7F4702EA535A1CE23E2D07EFCC1CCFBB3E95C86933C2F38767211B + +Count = 464 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D072A33CD208DB99AB14D909A1BF0897BBF + +Count = 465 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D07EF21C68BF5EC7F2A4961B68029496EF7 + +Count = 466 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D0776F05D2331CCF223A799138017E5E1E3 + +Count = 467 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D077B25FD0AE25FAD0981AAE45D12D4CD17 + +Count = 468 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D07973839894C7515A881AD72AF468A4D9B + +Count = 469 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D07EEF8B938DAA70DC4AA38C5E5A0931EA0 + +Count = 470 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D0762488AA4FCC188C5AF00EF3B30751387 + +Count = 471 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D072062A7CF044F3B3F49089007C39BE0CA + +Count = 472 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D0778112E397F616842EA3CC09140575D38 + +Count = 473 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D07D47630637AA5913E08C05CCDB42791AE + +Count = 474 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D07E6FCCB1FCF858B628823FEB8F3A0A6A5 + +Count = 475 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D0704B1767322E1332AD9CDDFEE2100E899 + +Count = 476 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D07A9BFAC68A66449929CD88220E68557C0 + +Count = 477 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D07ACCCD21751E521A110531B624EBF00C6 + +Count = 478 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D07289D8BA5DACAB79D539DB2D21BB7A6CA + +Count = 479 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D07E640F80692C803552C76E7FA8576ECE6 + +Count = 480 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D073DCF811972107A058FAF4C552AA208A4 + +Count = 481 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D07F52C9AF07AEC487FB049F9ED735E5520 + +Count = 482 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D0706977ACE61E2C14711DCEB3D4E96AA80 + +Count = 483 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D075717E9C320CBE237365D20B326D552E9 + +Count = 484 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D0705273A6A151DC0FB5B471DE46A8157EC + +Count = 485 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D0700E94705ABD6157C88A5FA142FA2666F + +Count = 486 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D07281F1B2419E47AF58FE68568A62024F0 + +Count = 487 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D074AB564346A8B688A7BE3D5716EF8079E + +Count = 488 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D070238640A6BE9549CA18BF7F82F53363A + +Count = 489 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D07CD1A4DC32F98271DC6B57E2B2E7729A5 + +Count = 490 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D07BCE2D112AB93289ADC107DF8029F6D10 + +Count = 491 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D0785A1B7B97F535D591EA270617B5AFE3E + +Count = 492 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D07B57F63BD8A7B106CA409B3D506EA0787 + +Count = 493 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D07ED04CDD9732DD643AAC284D7F63B0A38 + +Count = 494 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D07DBFAB0CEFF636DFF4F8A2962EE667799 + +Count = 495 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D074438E36752F104EA7B879DBB71102278 + +Count = 496 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F5030FDAE23A2BED9CF994E56BBE1E9CC + +Count = 497 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F95CF2C411525B1A0EB3A16BECC0FB368 + +Count = 498 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F50DD27EA6D70543BEFCB3A2515CFA620 + +Count = 499 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079FC90CBC42A950D93201339F252B632934 + +Count = 500 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079FC4D91C6B7AC38618270068F82E5205C0 + +Count = 501 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F28C4D8E8D4E93EB92707FE0A7A0C854C + +Count = 502 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F51045859423B26D50C9249409C15D677 + +Count = 503 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079FDDB46BC5645DA3D409AA639E0CF3DB50 + +Count = 504 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F9F9E46AE9CD3102EEFA21CA2FF1D281D + +Count = 505 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079FC7EDCF58E7FD43534C964C347CD195EF + +Count = 506 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F6B8AD102E239BA2FAE6AD06888A15979 + +Count = 507 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F59002A7E5719A0732E89721DCF266E72 + +Count = 508 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079FBB4D9712BA7D183B7F67534B1D86204E + +Count = 509 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F16434D093EF862833A720E85DA039F17 + +Count = 510 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F13303376C9790AB0B6F997C77239C811 + +Count = 511 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F97616AC442569C8CF5373E7727316E1D + +Count = 512 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F59BC19670A5428448ADC6B5FB9F02431 + +Count = 513 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F82336078EA8C51142905C0F01624C073 + +Count = 514 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F4AD07B91E270636E16E375484FD89DF7 + +Count = 515 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079FB96B9BAFF97EEA56B776679872106257 + +Count = 516 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079FE8EB08A2B857C92690F7AC161A539A3E + +Count = 517 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079FBADBDB0B8D81EBEAFDED914156079F3B + +Count = 518 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079FBF15A664334A3E6D2E0F76B11324AEB8 + +Count = 519 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F97E3FA45817851E4294C09CD9AA6EC27 + +Count = 520 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079FF5498555F217439BDD4959D4527ECF49 + +Count = 521 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079FBDC4856BF3757F8D07217B5D13D5FEED + +Count = 522 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F72E6ACA2B7040C0C601FF28E12F1E172 + +Count = 523 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F031E3073330F038B7ABAF15D3E19A5C7 + +Count = 524 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F3A5D56D8E7CF7648B808FCC447DC36E9 + +Count = 525 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F0A8382DC12E73B7D02A33F703A6CCF50 + +Count = 526 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F52F82CB8EBB1FD520C680872CABDC2EF + +Count = 527 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F640651AF67FF46EEE920A5C7D2E0BF4E + +Count = 528 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079FFBC40206CA6D2FFBDD2D111E4D96EAAF + +Count = 529 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B9096D461FC1B70AE3938A394172992C0 + +Count = 530 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B5569058ECA9C7FD71D9BFB7C60C7C864 + +Count = 531 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B907B0E25B2C99A4C196AD7E7B907DD2C + +Count = 532 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B09AA958D76E91745F79272E787AB5238 + +Count = 533 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B047F35A4A57A486FD1A1853A829A7ECC + +Count = 534 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7BE862F1270B50F0CED1A613C8D6C4FE40 + +Count = 535 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B91A271969D82E8A2FA33A48230DDAD7B + +Count = 536 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B1D12420ABBE46DA3FF0B8E5CA03BA05C + +Count = 537 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B5F386F61436ADE591903F16053D55311 + +Count = 538 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B074BE69738448D24BA37A1F6D019EEE3 + +Count = 539 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7BAB2CF8CD3D80745858CB3DAA24692275 + +Count = 540 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B99A603B188A06E04D8289FDF63EE157E + +Count = 541 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B7BEBBEDD65C4D64C89C6BE89B14E5B42 + +Count = 542 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7BD6E564C6E141ACF4CCD3E34776CBE41B + +Count = 543 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7BD3961AB916C0C4C740587A05DEF1B31D + +Count = 544 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B57C7430B9DEF52FB0396D3B58BF91511 + +Count = 545 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B991A30A8D5EDE6337C7D869D15385F3D + +Count = 546 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B429549B735359F63DFA42D32BAECBB7F + +Count = 547 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B8A76525E3DC9AD19E042988AE310E6FB + +Count = 548 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B79CDB26026C7242141D78A5ADED8195B + +Count = 549 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B284D216D67EE0751665641D4B69BE132 + +Count = 550 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B7A7DF2C45238259D0B4C7C83FACFE437 + +Count = 551 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B7FB38FABECF3F01AD8AE9B73BFECD5B4 + +Count = 552 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B5745D38A5EC19F93DFEDE40F366E972B + +Count = 553 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B35EFAC9A2DAE8DEC2BE8B416FEB6B445 + +Count = 554 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B7D62ACA42CCCB1FAF180969FBF1D85E1 + +Count = 555 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7BB240856D68BDC27B96BE1F4CBE399A7E + +Count = 556 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7BC3B819BCECB6CDFC8C1B1C9F92D1DECB + +Count = 557 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7BFAFB7F173876B83F4EA91106EB144DE5 + +Count = 558 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7BCA25AB13CD5EF50AF402D2B296A4B45C + +Count = 559 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B925E057734083325FAC9E5B06675B9E3 + +Count = 560 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7BA4A07860B84688991F8148057E28C442 + +Count = 561 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B3B622BC915D4E18C2B8CFCDCE15E91A3 + +Count = 562 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B628C9B9BC62D788F90572FED135FE6931B + +Count = 563 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6249644A291BFF80E9738CB5FB2808C9BF + +Count = 564 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B628C76418263AA6572777D9960F1C8DCF7 + +Count = 565 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6215A7DA2AA78AE87B99853C60CF6453E3 + +Count = 566 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6218727A037419B751BFB6CBBDCA557F17 + +Count = 567 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62F46FBE80DA330FF0BFB15D4F9E0BFF9B + +Count = 568 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B628DAF3E314CE1179C9424EA057812ACA0 + +Count = 569 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62011F0DAD6A87929D911CC0DBE8F4A187 + +Count = 570 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62433520C6920921677714BFE71B1A52CA + +Count = 571 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B621B46A930E927721AD420EF7198D6EF38 + +Count = 572 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62B721B76AECE38B6636DC732D6CA623AE + +Count = 573 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6285AB4C1659C3913AB63FD1582B2114A5 + +Count = 574 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6267E6F17AB4A72972E7D1F00EF9815A99 + +Count = 575 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62CAE82B61302253CAA2C4ADC03E04E5C0 + +Count = 576 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62CF9B551EC7A33BF92E4F3482963EB2C6 + +Count = 577 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B624BCA0CAC4C8CADC56D819D32C33614CA + +Count = 578 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6285177F0F048E190D126AC81A5DF75EE6 + +Count = 579 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B625E980610E456605DB1B363B5F223BAA4 + +Count = 580 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62967B1DF9ECAA52278E55D60DABDFE720 + +Count = 581 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6265C0FDC7F7A4DB1F2FC0C4DD96171880 + +Count = 582 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6234406ECAB68DF86F08410F53FE54E0E9 + +Count = 583 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B626670BD63835BDAA3655B3204B200E5EC + +Count = 584 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6263BEC00C3D900F24B6B9D5F4F723D46F + +Count = 585 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B624B489C2D8FA260ADB1FAAA887EA196F0 + +Count = 586 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6229E2E33DFCCD72D245FFFA91B679B59E + +Count = 587 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62616FE303FDAF4EC49F97D818F7D2843A + +Count = 588 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62AE4DCACAB9DE3D45F8A951CBF6F69BA5 + +Count = 589 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62DFB5561B3DD532C2E20C5218DA1EDF10 + +Count = 590 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62E6F630B0E915470120BE5F81A3DB4C3E + +Count = 591 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62D628E4B41C3D0A349A159C35DE6BB587 + +Count = 592 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B628E534AD0E56BCC1B94DEAB372EBAB838 + +Count = 593 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62B8AD37C7692577A77196068236E7C599 + +Count = 594 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62276F646EC4B71EB2459BB25BA9919078 + +Count = 595 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629958B63F3127C40FBA975DE8211515BC0B + +Count = 596 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999D49EEDE114300C3B3FEB0C962FBE6AF + +Count = 597 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299585BE5756916E558B70F9C52BB3BF3E7 + +Count = 598 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299C18A7EDDAD36685159F7395285977CF3 + +Count = 599 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299CC5FDEF47EA5377B7FC4CE8F80A65007 + +Count = 600 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629920421A77D08F8FDA7FC3587DD4F8D08B + +Count = 601 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629959829AC6465D97B65456EF3732E183B0 + +Count = 602 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299D532A95A603B12B7516EC5E9A2078E97 + +Count = 603 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999718843198B5A14DB766BAD551E97DDA + +Count = 604 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299CF6B0DC7E39BF2301452EA43D225C028 + +Count = 605 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299630C139DE65F0B4CF6AE761F26550CBE + +Count = 606 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62995186E8E1537F1110764DD46A61D23BB5 + +Count = 607 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B3CB558DBE1BA95827A3F53CB3727589 + +Count = 608 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62991EC58F963A9ED3E062B6A8F274F7CAD0 + +Count = 609 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62991BB6F1E9CD1FBBD3EE3D31B0DCCD9DD6 + +Count = 610 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999FE7A85B46302DEFADF3980089C53BDA + +Count = 611 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299513ADBF80E329927D218CD28170471F6 + +Count = 612 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62998AB5A2E7EEEAE07771C16687B8D095B4 + +Count = 613 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62994256B90EE616D20D4E27D33FE12CC830 + +Count = 614 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B1ED5930FD185B35EFB2C1EFDCE43790 + +Count = 615 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299E06DCA3DBC317845C8330A61B4A7CFF9 + +Count = 616 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B25D199489E75A89A5293736F8F3CAFC + +Count = 617 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B79364FB372C8F0E76CBD0C6BDD0FB7F + +Count = 618 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62999F6538DA851EE0877188AFBA3452B9E0 + +Count = 619 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299FDCF47CAF671F2F8858DFFA3FC8A9A8E + +Count = 620 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299B54247F4F713CEEE5FE5DD2ABD21AB2A + +Count = 621 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997A606E3DB362BD6F38DB54F9BC05B4B5 + +Count = 622 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62990B98F2EC3769B2E8227E572A90EDF000 + +Count = 623 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629932DB9447E3A9C72BE0CC5AB3E928632E + +Count = 624 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62990205404316818A1E5A67990794989A97 + +Count = 625 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62995A7EEE27EFD74C3154ACAE0564499728 + +Count = 626 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62996C8093306399F78DB1E403B07C14EA89 + +Count = 627 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299F342C099CE0B9E9885E9B769E362BF68 + +Count = 628 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997969C2D9DA08ABA81C8EFB9CDABF0ECC43 + +Count = 629 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AC3D08353E2CA765AA58C432C8E096E7 + +Count = 630 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979692F039E467942FEAEA9E8A9112083AF + +Count = 631 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979F0FE98368259CFF740514DA92F8C0CBB + +Count = 632 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979FD2B381F51CA90DD6662BA742ABD204F + +Count = 633 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299791136FC9CFFE0287C66652C867EE3A0C3 + +Count = 634 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997968F67C2D693230104DF09BCC98FAF3F8 + +Count = 635 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979E4464FB14F54B51148C8B112081CFEDF + +Count = 636 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A66C62DAB7DA06EBAEC0CE2EFBF20D92 + +Count = 637 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979FE1FEB2CCCF455960DF49EB8783EB060 + +Count = 638 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299795278F576C930ACEAEF0802E48C4E7CF6 + +Count = 639 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997960F20E0A7C10B6B66FEBA091CBC94BFD + +Count = 640 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997982BFB36691740EFE3E0581C7196905C1 + +Count = 641 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299792FB1697D15F174467B10DC09DEECBA98 + +Count = 642 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299792AC21702E2701C75F79B454B76D6ED9E + +Count = 643 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AE934EB0695F8A49B455ECFB23DE4B92 + +Count = 644 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979604E3D13215D3E81CBBEB9D3BD1F01BE + +Count = 645 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979BBC1440CC18547D16867127C12CBE5FC + +Count = 646 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997973225FE5C97975AB5781A7C44B37B878 + +Count = 647 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798099BFDBD277FC93F614B51476FF47D8 + +Count = 648 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979D1192CD6935EDFE3D1957E9A1EBCBFB1 + +Count = 649 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798329FF7FA688FD2FBC8F43CD52E8BAB4 + +Count = 650 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997986E78210184328A86F6DA43D17CB8B37 + +Count = 651 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979AE11DE31AA714721682EDB419E49C9A8 + +Count = 652 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979CCBBA121D91E555E9C2B8B585691EAC6 + +Count = 653 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299798436A11FD87C69484643A9D1173ADB62 + +Count = 654 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299794B1488D69C0D1AC9217D2002161EC4FD + +Count = 655 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299793AEC14071806154E3BD823D13AF68048 + +Count = 656 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B62997903AF72ACCCC6608DF96A2E4843331366 + +Count = 657 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299793371A6A839EE2DB843C1EDFC3E83EADF + +Count = 658 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299796B0A08CCC0B8EB974D0ADAFECE52E760 + +Count = 659 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B6299795DF475DB4CF6502BA842774BD60F9AC1 + +Count = 660 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979C2362672E164393E9C4FC3924979CF20 + +Count = 661 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B9A593097205AA96CD53AB48F8592FAC + +Count = 662 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27C5A42E64482A5EFE9F0F3A08FB77508 + +Count = 663 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B948494D3CD74074ED01DF3B56776040 + +Count = 664 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22099D2E5F8F7CD7D03F97A3B68DBEF54 + +Count = 665 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22D4C72CC2B64925725CA8DE66DEAC3A0 + +Count = 666 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2C151B64F854E2AF625CD1B1439B4432C + +Count = 667 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B89136FE139C329A0E58AC5EDFAD1017 + +Count = 668 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A23421056235FAB79B0B6086804F4B1D30 + +Count = 669 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2760B2809CD740461ED68F9BCBCA5EE7D + +Count = 670 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A22E78A1FFB65A571C4E5CA92A3F69538F + +Count = 671 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2821FBFA5B39EAE60ACA03576CB199F19 + +Count = 672 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B09544D906BEB43C2C4397038C9EA812 + +Count = 673 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A252D8F9B5EBDA0C747DADB6555E3EE62E + +Count = 674 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2FFD623AE6F5F76CC38B8EB9B99BB5977 + +Count = 675 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2FAA55DD198DE1EFFB43372D931810E71 + +Count = 676 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27EF4046313F188C3F7FDDB696489A87D + +Count = 677 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2B02977C05BF33C0B88168E41FA48E251 + +Count = 678 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A26BA60EDFBB2B455B2BCF25EE559C0613 + +Count = 679 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2A3451536B3D77721142990560C605B97 + +Count = 680 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A250FEF508A8D9FE19B5BC828631A8A437 + +Count = 681 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2017E6605E9F0DD69923D490859EB5C5E + +Count = 682 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2534EB5ACDC26FFA5FF27745F15BF595B + +Count = 683 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A25680C8C362ED2A222CC593AF509C68D8 + +Count = 684 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A27E7694E2D0DF45AB2B86ECD3D91E2A47 + +Count = 685 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A21CDCEBF2A3B057D4DF83BCCA11C60929 + +Count = 686 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A25451EBCCA2D26BC205EB9E43506D388D + +Count = 687 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A29B73C205E6A3184362D5179051492712 + +Count = 688 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2EA8B5ED462A817C4787014437DA163A7 + +Count = 689 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2D3C8387FB6686207BAC219DA0464F089 + +Count = 690 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2E316EC7B43402F320069DA6E79D40930 + +Count = 691 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2BB6D421FBA16E91D0EA2ED6C8905048F + +Count = 692 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A28D933F08365852A1EBEA40D99158792E + +Count = 693 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A212516CA19BCA3BB4DFE7F4000E2E2CCF + +Count = 694 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240434EE6A09FEDD4F51F39952D0B84AB3E + +Count = 695 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24086B1374FA96ADB8C3B9ACDC57C6AF19A + +Count = 696 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24043A33CE4D13F3E173F6BE15EA5AAE4D2 + +Count = 697 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240DA72A74C151FB31ED193445E9B066BC6 + +Count = 698 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240D7A70765C68CEC34F7A0B3839E374732 + +Count = 699 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403BBAC3E668A65495F7A72571CA69C7BE + +Count = 700 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240427A4357FE744CF9DC32923B2C709485 + +Count = 701 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240CECA70CBD812C9F8D90AB8E5BC9699A2 + +Count = 702 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2408CE05DA0209C7A023F02C7D94F786AEF + +Count = 703 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240D493D4565BB2297F9C36974FCCB4D71D + +Count = 704 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24078F4CA0C5E76D0037ECA0B1338C41B8B + +Count = 705 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2404A7E3170EB56CA5FFE29A9667F432C80 + +Count = 706 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240A8338C1C06327217AFC78830ADE362BC + +Count = 707 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240053D560782B708AFEAD2D5FE6A66DDE5 + +Count = 708 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240004E28787536609C66594CBCC25C8AE3 + +Count = 709 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240841F71CAFE19F6A02597E50C97542CEF + +Count = 710 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2404AC20269B61B42685A7CB024099566C3 + +Count = 711 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240914D7B7656C33B38F9A51B8BA6418281 + +Count = 712 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24059AE609F5E3F0942C643AE33FFBDDF05 + +Count = 713 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AA1580A14531807A67D6BCE3C27520A5 + +Count = 714 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240FB9513AC0418A30A4057776DAA36D8CC + +Count = 715 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240A9A5C00531CE81C62D4D4A3AE662DDC9 + +Count = 716 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AC6BBD6A8F055441FEAFADCAA341EC4A + +Count = 717 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240849DE14B3D373BC8F9ECD2B62AC3AED5 + +Count = 718 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240E6379E5B4E5829B70DE982AFE21B8DBB + +Count = 719 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240AEBA9E654F3A15A1D781A026A3B0BC1F + +Count = 720 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2406198B7AC0B4B6620B0BF29F5A294A380 + +Count = 721 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24010602B7D8F4069A7AA1A2A268E7CE735 + +Count = 722 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24029234DD65B801C6468A827BFF7B9741B + +Count = 723 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24019FD99D2AEA85151D203E40B8A098DA2 + +Count = 724 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240418637B657FE977EDCC8D3097AD8801D + +Count = 725 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A24077784AA1DBB02CC239807EBC6285FDBC + +Count = 726 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A240E8BA1908762245D70D8DCA65FDF3A85D + +Count = 727 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D546FE67094BB75016786E3EA9E6A5BCD + +Count = 728 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9190379FA23C7A784325BB02E9840169 + +Count = 729 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D54823C34DA699FE347D4979930441421 + +Count = 730 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DCD53A79C1E4912EAA92C32990EE89B35 + +Count = 731 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DC08607B5CDDA4DC08F1FC5440BD9B7C1 + +Count = 732 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D2C9BC33663F0F5618F1853B65F87374D + +Count = 733 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D555B4387F522ED0DA48DE4FCB99E6476 + +Count = 734 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DD9EB701BD344680CA1B5CE2229786951 + +Count = 735 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9BC15D702BCADBF647BDB11EDA969A1C + +Count = 736 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DC3B2D48650E4888BE489E188595A27EE + +Count = 737 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D6FD5CADC552071F706757DD4AD2AEB78 + +Count = 738 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D5D5F31A0E0006BAB8696DFA1EAADDC73 + +Count = 739 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBF128CCC0D64D3E3D778FEF7380D924F + +Count = 740 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D121C56D789E1A95B926DA339FF882D16 + +Count = 741 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D176F28A87E60C1681EE63A7B57B27A10 + +Count = 742 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D933E711AF54F57545D2893CB02BADC1C + +Count = 743 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D5DE302B9BD4DE39C22C3C6E39C7B9630 + +Count = 744 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D866C7BA65D959ACC811A6D4C33AF7272 + +Count = 745 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D4E8F604F5569A8B6BEFCD8F46A532FF6 + +Count = 746 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBD3480714E67218E1F69CA24579BD056 + +Count = 747 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DECB4137C0F4E02FE38E801AA3FD8283F + +Count = 748 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBE84C0D53A98203255F23CFD738C2D3A + +Count = 749 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DBB4ABDBA8453F5B58610DB0D36AF1CB9 + +Count = 750 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D93BCE19B36619A3C8153A471BF2D5E26 + +Count = 751 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DF1169E8B450E88437556F46877F57D48 + +Count = 752 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DB99B9EB5446CB455AF3ED6E1365E4CEC + +Count = 753 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D76B9B77C001DC7D4C8005F32377A5373 + +Count = 754 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D07412BAD8416C853D2A55CE11B9217C6 + +Count = 755 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D3E024D0650D6BD9010175178625784E8 + +Count = 756 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D0EDC9902A5FEF0A5AABC92CC1FE77D51 + +Count = 757 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D56A737665CA8368AA477A5CEEF3670EE + +Count = 758 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D60594A71D0E68D36413F087BF76B0D4F + +Count = 759 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403DFF9B19D87D74E4237532BCA2681D58AE + +Count = 760 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9F02DA748370296F34EA79F4E5497D6D + +Count = 761 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F5AFD0B9BB5F726161049211C92A727C9 + +Count = 762 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9FEF0030CDA2C38D14B80D874B673281 + +Count = 763 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F063E9B9809824E84FA40A88775CBBD95 + +Count = 764 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F0BEB3BB1DA1111AEDC735F5A70FA9161 + +Count = 765 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FE7F6FF32743BA90FDC74C9A824A411ED + +Count = 766 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9E367F83E2E9B163F7E17EE2C2BD42D6 + +Count = 767 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F12864C1FC48F3462F2D9543C525B4FF1 + +Count = 768 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F50AC61743C01879814D12B00A1B5BCBC + +Count = 769 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F08DFE882472FD4E5B7E57B962279014E + +Count = 770 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FA4B8F6D842EB2D995519E7CAD609CDD8 + +Count = 771 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F96320DA4F7CB37C5D5FA45BF918EFAD3 + +Count = 772 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F747FB0C81AAF8F8D841464E9432EB4EF + +Count = 773 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FD9716AD39E2AF535C101392784AB0BB6 + +Count = 774 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FDC0214AC69AB9D064D8AA0652C915CB0 + +Count = 775 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F58534D1EE2840B3A0E4409D57999FABC + +Count = 776 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F968E3EBDAA86BFF271AF5CFDE758B090 + +Count = 777 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F4D0147A24A5EC6A2D276F752488C54D2 + +Count = 778 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F85E25C4B42A2F4D8ED9042EA11700956 + +Count = 779 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F7659BC7559AC7DE04C05503A2CB8F6F6 + +Count = 780 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F27D92F7818855E906B849BB444FB0E9F + +Count = 781 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F75E9FCD12D537C5C069EA6E308AF0B9A + +Count = 782 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F702781BE9398A9DBD57C41134D8C3A19 + +Count = 783 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F58D1DD9F21AAC652D23F3E6FC40E7886 + +Count = 784 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F3A7BA28F52C5D42D263A6E760CD65BE8 + +Count = 785 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F72F6A2B153A7E83BFC524CFF4D7D6A4C + +Count = 786 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FBDD48B7817D69BBA9B6CC52C4C5975D3 + +Count = 787 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FCC2C17A993DD943D81C9C6FF60B13166 + +Count = 788 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FF56F7102471DE1FE437BCB661974A248 + +Count = 789 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FC5B1A506B235ACCBF9D008D264C45BF1 + +Count = 790 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F9DCA0B624B636AE4F71B3FD09415564E + +Count = 791 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9FAB347675C72DD158125392658C482BEF + +Count = 792 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F34F625DC6ABFB84D265E26BC133E7E0E + +Count = 793 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEB338400A1628D9BDBA44BD09814A472 + +Count = 794 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2ECC55EF97E582E2FF071338EFFAFED6 + +Count = 795 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEBDE5E44EFB06779FBF63FA3363AEB9E + +Count = 796 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F720FC5EC2B90EA70150E9AA30896648A + +Count = 797 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F7FDA65C5F803B55A333D6D7E0DA7487E + +Count = 798 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F93C7A14656290DFB333AFB8C59F9C8F2 + +Count = 799 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FEA0721F7C0FB159718AF4CC6BFE09BC9 + +Count = 800 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F66B7126BE69D90961D9766182F0696EE + +Count = 801 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F249D3F001E13236CFB9F1924DCE865A3 + +Count = 802 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F7CEEB6F6653D701158AB49B25F24D851 + +Count = 803 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FD089A8AC60F9896DBA57D5EEAB5414C7 + +Count = 804 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE20353D0D5D993313AB4779BECD323CC + +Count = 805 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F004EEEBC38BD2B796B5A56CD3E736DF0 + +Count = 806 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FAD4034A7BC3851C12E4F0B03F9F6D2A9 + +Count = 807 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FA8334AD84BB939F2A2C4924151CC85AF + +Count = 808 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2C62136AC096AFCEE10A3BF104C423A3 + +Count = 809 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE2BF60C988941B069EE16ED99A05698F + +Count = 810 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F393019D6684C62563D38C57635D18DCD + +Count = 811 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FF1D3023F60B0502C02DE70CE6C2DD049 + +Count = 812 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F0268E2017BBED914A34B621E51E52FE9 + +Count = 813 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F53E8710C3A97FA6484CAA99039A6D780 + +Count = 814 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F01D8A2A50F41D8A8E9D094C775F2D285 + +Count = 815 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F0416DFCAB18A0D2F3A32733730D1E306 + +Count = 816 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F2CE083EB03B862A63D710C4BB953A199 + +Count = 817 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F4E4AFCFB70D770D9C9745C52718B82F7 + +Count = 818 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F06C7FCC571B54CCF131C7EDB3020B353 + +Count = 819 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FC9E5D50C35C43F4E7422F7083104ACCC + +Count = 820 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FB81D49DDB1CF30C96E87F4DB1DECE879 + +Count = 821 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F815E2F76650F450AAC35F94264297B57 + +Count = 822 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FB180FB729027083F169E3AF6199982EE + +Count = 823 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FE9FB55166971CE1018550DF4E9488F51 + +Count = 824 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6FDF052801E53F75ACFD1DA041F115F2F0 + +Count = 825 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F1011121314151617 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F40C77BA848AD1CB9C91014986E63A711 + +Count = 826 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C64EED4250F2974316283EDF1239D4504 + +Count = 827 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA11105CA39AE7B484620B51954731FA0 + +Count = 828 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C64030E6141FB9ED342D199828DB30AE8 + +Count = 829 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CFDD295C985DB13DAAC293C82B31F85FC + +Count = 830 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CF00735E056484CF08A1ACB5FB62EA908 + +Count = 831 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C1C1AF163F862F4518A1D5DADE2702984 + +Count = 832 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C65DA71D26EB0EC3DA188EAE704697ABF + +Count = 833 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CE96A424E48D6693CA4B0C039948F7798 + +Count = 834 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CAB406F25B058DAC642B8BF05676184D5 + +Count = 835 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CF333E6D3CB7689BBE18CEF93E4AD3927 + +Count = 836 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C5F54F889CEB270C7037073CF10DDF5B1 + +Count = 837 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C6DDE03F57B926A9B8393D1BA575AC2BA + +Count = 838 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8F93BE9996F6D2D3D27DF0EC85FA8C86 + +Count = 839 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C229D64821273A86B9768AD22427F33DF + +Count = 840 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C27EE1AFDE5F2C0581BE33460EA4564D9 + +Count = 841 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA3BF434F6EDD5664582D9DD0BF4DC2D5 + +Count = 842 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C6D6230EC26DFE2AC27C6C8F8218C88F9 + +Count = 843 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CB6ED49F3C6079BFC841F63578E586CBB + +Count = 844 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C7E0E521ACEFBA986BBF9D6EFD7A4313F + +Count = 845 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8DB5B224D5F520BE1A6CC43FEA6CCE9F + +Count = 846 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CDC35212994DC03CE3DED0FB1822F36F6 + +Count = 847 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8E05F280A10A210250F732E6CE7B33F3 + +Count = 848 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C8BCB8FEF1FC1F4858315D5168B580270 + +Count = 849 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CA33DD3CEADF39B0C8456AA6A02DA40EF + +Count = 850 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CC197ACDEDE9C89737053FA73CA026381 + +Count = 851 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C891AACE0DFFEB565AA3BD8FA8BA95225 + +Count = 852 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C463885299B8FC6E4CD0551298A8D4DBA + +Count = 853 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C37C019F81F84C963D7A052FAA665090F + +Count = 854 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C0E837F53CB44BCA015125F63DFA09A21 + +Count = 855 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C3E5DAB573E6CF195AFB99CD7A2106398 + +Count = 856 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C66260533C73A37BAA172ABD552C16E27 + +Count = 857 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9C50D878244B748C06443A06604A9C1386 + +Count = 858 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CCF1A2B8DE6E6E5137037B2B9D5EA4667 + +Count = 859 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA07F036BA47E86F5A423E3F84EB9C614F + +Count = 860 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC20FE755716F6023669D676C9C723BEB + +Count = 861 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA071DECFE093A85B8626C4BF745B22EA3 + +Count = 862 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA9ECC7756CD1A08B18C94EEF77B1EA1B7 + +Count = 863 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA9319D77F1E89579BAAA7192A7E2F8D43 + +Count = 864 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA7F0413FCB0A3EF3AAAA08FD82A710DCF + +Count = 865 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA06C4934D2671F75681353892CC685EF4 + +Count = 866 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA8A74A0D100177257840D124C5C8E53D3 + +Count = 867 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC85E8DBAF899C1AD62056D70AF60A09E + +Count = 868 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA902D044C83B792D0C1313DE62CAC1D6C + +Count = 869 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA3C4A1A1686736BAC23CDA1BAD8DCD1FA + +Count = 870 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0EC0E16A335371F0A32E03CF9F5BE6F1 + +Count = 871 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEC8D5C06DE37C9B8F2C022994DFBA8CD + +Count = 872 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA4183861D5AB2B300B7D57F578A7E1794 + +Count = 873 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA44F0F862AD33DB333B5EE61522444092 + +Count = 874 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC0A1A1D0261C4D0F78904FA5774CE69E + +Count = 875 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0E7CD2736E1EF9C7077B1A8DE98DACB2 + +Count = 876 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAD5F3AB6C8EC68097A4A2B122465948F0 + +Count = 877 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA1D10B085863AB2ED9B44049A1FA51574 + +Count = 878 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEEAB50BB9D343BD53AD1164A226DEAD4 + +Count = 879 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBABF2BC3B6DC1D18A51D50DDC44A2E12BD + +Count = 880 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAED1B101FE9CB3A69704AE093067A17B8 + +Count = 881 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAE8D56D705700EFEEA3A807634359263B + +Count = 882 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAC0233151E5328067A4EB781FCADB64A4 + +Count = 883 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAA2894E41965D921850EE2806020347CA + +Count = 884 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAEA044E7F973FAE0E8A860A8F43A8766E + +Count = 885 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA252667B6D34EDD8FEDB8835C428C69F1 + +Count = 886 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA54DEFB675745D208F71D808F6E642D44 + +Count = 887 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA6D9D9DCC8385A7CB35AF8D1617A1BE6A + +Count = 888 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA5D4349C876ADEAFE8F044EA26A1147D3 + +Count = 889 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA0538E7AC8FFB2CD181CF79A09AC04A6C + +Count = 890 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA33C69ABB03B5976D6487D415829D37CD + +Count = 891 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F10111213141516171819 +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBAAC04C912AE27FE78508A60CC1DEB622C + +Count = 892 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250F0927D72D857E36CAD703B28EF139FA + +Count = 893 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25CAF6F6381B02714FEE745B5AF91F635E + +Count = 894 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250FE4FD93635794D4EA8577C120DF7616 + +Count = 895 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259635663BA77719DD047DD2C11E73F902 + +Count = 896 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259BE0C61274E446F7224E251C1B42D5F6 + +Count = 897 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2577FD0291DACEFE562249B3EE4F1C557A + +Count = 898 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250E3D82204C1CE63A09DC04A4A9050641 + +Count = 899 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25828DB1BC6A7A633B0CE42E7A39E30B66 + +Count = 900 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C0A79CD792F4D0C1EAEC5146CA0DF82B + +Count = 901 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2598D41521E9DA83BC49D801D049C145D9 + +Count = 902 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2534B30B7BEC1E7AC0AB249D8CBDB1894F + +Count = 903 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250639F007593E609C2BC73FF9FA36BE44 + +Count = 904 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E4744D6BB45AD8D47A291EAF2896F078 + +Count = 905 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25497A977030DFA26C3F3C4361EF134F21 + +Count = 906 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA254C09E90FC75ECA5FB3B7DA2347291827 + +Count = 907 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C858B0BD4C715C63F07973931221BE2B + +Count = 908 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250685C31E0473E8AB8F9226BB8CE0F407 + +Count = 909 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25DD0ABA01E4AB91FB2C4B8D1423341045 + +Count = 910 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2515E9A1E8EC57A38113AD38AC7AC84DC1 + +Count = 911 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E65241D6F7592AB9B2382A7C4700B261 + +Count = 912 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25B7D2D2DBB67009C995B9E1F22F434A08 + +Count = 913 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E5E2017283A62B05F8A3DCA563174F0D + +Count = 914 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E02C7C1D3D6DFE822B413B5526347E8E + +Count = 915 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25C8DA203C8F5F910B2C024429AFB63C11 + +Count = 916 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25AA705F2CFC308374D8071430676E1F7F + +Count = 917 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25E2FD5F12FD52BF62026F36B926C52EDB + +Count = 918 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA252DDF76DBB923CCE36551BF6A27E13144 + +Count = 919 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA255C27EA0A3D28C3647FF4BCB90B0975F1 + +Count = 920 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2565648CA1E9E8B6A7BD46B12072CCE6DF + +Count = 921 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA2555BA58A51CC0FB9207ED72940F7C1F66 + +Count = 922 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA250DC1F6C1E5963DBD09264596FFAD12D9 + +Count = 923 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA253B3F8BD669D88601EC6EE823E7F06F78 + +Count = 924 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA25A4FDD87FC44AEF14D8635CFA78863A99 + +Count = 925 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCE72A8718C1BF9A53B646BE0293BB8CF + +Count = 926 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D0B8D799EBA9CF6DC1FC733085ED5E26B + +Count = 927 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCE9F7235C2C913471B361F938715F723 + +Count = 928 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D574EE99D06E99E4EF5CEBA93B9B97837 + +Count = 929 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D5A9B49B4D57AC164D3FD4D4EBC8854C3 + +Count = 930 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DB6868D377B5079C5D3FADBBCE8D6D44F + +Count = 931 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCF460D86ED8261A9F86F6CF60ECF8774 + +Count = 932 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D43F63E1ACBE4E4A8FD5746289E298A53 + +Count = 933 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D01DC1371336A57521B5F39146DC7791E + +Count = 934 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D59AF9A874844042FB86B6982EE0BC4EC + +Count = 935 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DF5C884DD4D80FD535A97F5DE1A7B087A + +Count = 936 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DC7427FA1F8A0E70FDA7457AB5DFC3F71 + +Count = 937 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D250FC2CD15C45F478B9A76FD8F5C714D + +Count = 938 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D880118D6914125FFCE8F2B3348D9CE14 + +Count = 939 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D8D7266A966C04DCC4204B271E0E39912 + +Count = 940 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D09233F1BEDEFDBF001CA1BC1B5EB3F1E + +Count = 941 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DC7FE4CB8A5ED6F387E214EE92B2A7532 + +Count = 942 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D1C7135A745351668DDF8E54684FE9170 + +Count = 943 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DD4922E4E4DC92412E21E50FEDD02CCF4 + +Count = 944 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2729CE7056C7AD2A438B422EE0CA3354 + +Count = 945 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D76A95D7D17EE8E5A640A89A08889CB3D + +Count = 946 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D24998ED42238AC960910B4F7C4DDCE38 + +Count = 947 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2157F3BB9CF37911DAF2530781FEFFBB + +Count = 948 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D09A1AF9A2EC11698DDB12C7B087CBD24 + +Count = 949 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D6B0BD08A5DAE04E729B47C62C0A49E4A + +Count = 950 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D2386D0B45CCC38F1F3DC5EEB810FAFEE + +Count = 951 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DECA4F97D18BD4B7094E2D738802BB071 + +Count = 952 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D9D5C65AC9CB644F78E47D4EBACC3F4C4 + +Count = 953 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DA41F0307487631344CF5D972D50667EA + +Count = 954 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D94C1D703BD5E7C01F65E1AC6A8B69E53 + +Count = 955 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DCCBA79674408BA2EF8952DC4586793EC + +Count = 956 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DFA440470C84601921DDD8071403AEE4D + +Count = 957 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259D658657D965D4688729D034A8DF4CBBAC + +Count = 958 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4AE2A91E60E75157A9577109369DB8DF + +Count = 959 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8F1D78F156605E2E8DF429E14173E27B + +Count = 960 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4A0F735A2E35BBB58905057A98B3F733 + +Count = 961 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABD3DEE8F2EA1536BC67FDA07AA61F7827 + +Count = 962 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABDE0B48DB3986699641CE57A7A32E54D3 + +Count = 963 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB32168C5897ACD13741C9C155F770D45F + +Count = 964 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB4BD60CE9017EC95B6A5C761F11698764 + +Count = 965 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABC7663F7527184C5A6F645CC1818F8A43 + +Count = 966 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB854C121EDF96FFA0896C23FD7261790E + +Count = 967 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABDD3F9BE8A4B8ACDD2A58736BF1ADC4FC + +Count = 968 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB715885B2A17C55A1C8A4EF3705DD086A + +Count = 969 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB43D27ECE145C4FFD48474D42425A3F61 + +Count = 970 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA19FC3A2F938F7B519A96C1490FA715D + +Count = 971 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB0C9119B97DBD8D0D5CBC31DA577FCE04 + +Count = 972 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB09E267C68A3CE53ED037A898FF459902 + +Count = 973 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8DB33E740113730293F90128AA4D3F0E + +Count = 974 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB436E4DD74911C7CAEC125400348C7522 + +Count = 975 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB98E134C8A9C9BE9A4FCBFFAF9B589160 + +Count = 976 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB50022F21A1358CE0702D4A17C2A4CCE4 + +Count = 977 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA3B9CF1FBA3B05D8D1B858C7FF6C3344 + +Count = 978 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABF2395C12FB1226A8F6399349972FCB2D + +Count = 979 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA0098FBBCEC404649B23AE1EDB7BCE28 + +Count = 980 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA5C7F2D4700FD1E348C149EE9E58FFAB + +Count = 981 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB8D31AEF5C23DBE6A4F82369217DABD34 + +Count = 982 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABEF9BD1E5B152AC15BB87668BDF029E5A + +Count = 983 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABA716D1DBB030900361EF44029EA9AFFE + +Count = 984 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6834F812F441E38206D1CDD19F8DB061 + +Count = 985 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB19CC64C3704AEC051C74CE02B365F4D4 + +Count = 986 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB208F0268A48A99C6DEC6C39BCAA067FA + +Count = 987 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB1051D66C51A2D4F3646D002FB7109E43 + +Count = 988 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB482A7808A8F412DC6AA6372D47C193FC + +Count = 989 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB7ED4051F24BAA9608FEE9A985F9CEE5D + +Count = 990 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DABE11656B68928C075BBE32E41C0EABBBC + +Count = 991 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4D70746F2D2879F989505D58F7ACA95C + +Count = 992 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F888FA5801BAF7680ADF305B08042F3F8 + +Count = 993 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4D9DAE2B63FA931BA902292B5982E6B0 + +Count = 994 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FD44C3583A7DA1E1247FA8C2B672E69A4 + +Count = 995 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FD99995AA7449413861C97BF6621F4550 + +Count = 996 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F35845129DA63F99961CEED043641C5DC + +Count = 997 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4C44D1984CB1E1F54A5B5A4ED05896E7 + +Count = 998 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FC0F4E2046AD764F44F63709040BE9BC0 + +Count = 999 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F82DECF6F9259D70EA96B0FACB350688D + +Count = 1000 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FDAAD4699E97784730A5F5F3A309CD57F + +Count = 1001 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F76CA58C3ECB37D0FE8A3C366C4EC19E9 + +Count = 1002 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4440A3BF5993675368406113836B2EE2 + +Count = 1003 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA60D1ED3B4F7DF1B39AE404551CB60DE + +Count = 1004 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F0B03C4C83072A5A37CBB1D8B964EDF87 + +Count = 1005 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F0E70BAB7C7F3CD90F03084C93E748881 + +Count = 1006 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F8A21E3054CDC5BACB3FE2D796B7C2E8D + +Count = 1007 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F44FC90A604DEEF64CC157851F5BD64A1 + +Count = 1008 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F9F73E9B9E40696346FCCD3FE5A6980E3 + +Count = 1009 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F5790F250ECFAA44E502A66460395DD67 + +Count = 1010 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA42B126EF7F42D76F1BF74963E5D22C7 + +Count = 1011 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FF5AB8163B6DD0E06D63EBF18561EDAAE + +Count = 1012 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA79B52CA830B2CCABB24824F1A4ADFAB + +Count = 1013 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA2552FA53DC0F94D68C665BF5F69EE28 + +Count = 1014 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F8AA373848FF296C46F851AC3D6EBACB7 + +Count = 1015 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FE8090C94FC9D84BB9B804ADA1E338FD9 + +Count = 1016 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FA0840CAAFDFFB8AD41E868535F98BE7D + +Count = 1017 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F6FA62563B98ECB2C26D6E1805EBCA1E2 + +Count = 1018 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F1E5EB9B23D85C4AB3C73E2537254E557 + +Count = 1019 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F271DDF19E945B168FEC1EFCA0B917679 + +Count = 1020 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F17C30B1D1C6DFC5D446A2C7E76218FC0 + +Count = 1021 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F4FB8A579E53B3A724AA11B7C86F0827F + +Count = 1022 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7946D86E697581CEAFE9B6C99EADFFDE + +Count = 1023 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6FE6848BC7C4E7E8DB9BE4021001DBAA3F + +Count = 1024 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7E4CC94143EC866BA90EF8B4A00D3652 + +Count = 1025 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EBBB318AE756B89128DADA05CD7E36CF6 + +Count = 1026 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7EA113050D3E6C89895C8CC70E2379BE + +Count = 1027 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EE77088ADC91EE18067A429C7308FF6AA + +Count = 1028 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EEAA528841A8DBEAA4197DE1A35BEDA5E + +Count = 1029 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E06B8EC07B4A7060B419048E861E05AD2 + +Count = 1030 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7F786CB622751E676A05FFA287F909E9 + +Count = 1031 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EF3C85F2A04139B666F3DD57C171F04CE + +Count = 1032 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB1E27241FC9D289C8935AA40E4F1F783 + +Count = 1033 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EE991FBB787B37BE12A01FAD6673D4A71 + +Count = 1034 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E45F6E5ED8277829DC8FD668A934D86E7 + +Count = 1035 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E777C1E91375798C1481EC4FFD4CAB1EC + +Count = 1036 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9531A3FDDA33208919F0E5A9066AFFD0 + +Count = 1037 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E383F79E65EB65A315CE5B867C1EF4089 + +Count = 1038 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E3D4C0799A9373202D06E212569D5178F + +Count = 1039 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB91D5E2B2218A43E93A088953CDDB183 + +Count = 1040 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E77C02D886A1A10F6EC4BDDBDA21CFBAF + +Count = 1041 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EAC4F54978AC269A64F9276120DC81FED + +Count = 1042 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E64AC4F7E823E5BDC7074C3AA54344269 + +Count = 1043 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9717AF409930D2E4D1E1D17A69FCBDC9 + +Count = 1044 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EC6973C4DD819F194F6601AF401BF45A0 + +Count = 1045 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E94A7EFE4EDCFD3589B7A27A34DEB40A5 + +Count = 1046 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E9169928B530406DF4898C05308C87126 + +Count = 1047 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EB99FCEAAE13669564FDBBF2F814A33B9 + +Count = 1048 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7EDB35B1BA92597B29BBDEEF36499210D7 + +Count = 1049 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E93B8B184933B473F61B6CDBF08392173 + +Count = 1050 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5C9A984DD74A34BE0688446C091D3EEC + +Count = 1051 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E2D62049C53413B391C2D47BF25F57A59 + +Count = 1052 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E1421623787814EFADE9F4A265C30E977 + +Count = 1053 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E24FFB63372A903CF64348992218010CE + +Count = 1054 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E7C8418578BFFC5E06AFFBE90D1511D71 + +Count = 1055 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E4A7A654007B17E5C8FB71325C90C60D0 + +Count = 1056 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7ED5B836E9AA231749BBBAA7FC567A3531 + +Count = 1057 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDD94B5A9DC1B1E0E4B67D163F605735C + +Count = 1058 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B186B6446EA9C11776FC4898B81EB29F8 + +Count = 1059 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDD796FED92C9F4EC6B35A510582B3CB0 + +Count = 1060 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B44A8F44556E979E585CD00106687B3A4 + +Count = 1061 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B497D546C857A26CFA3FEF7CD63B69F50 + +Count = 1062 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BA56090EF2B509E6EA3F9613F37E81FDC + +Count = 1063 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDCA0105EBD828602886CD675D1F14CE7 + +Count = 1064 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B501023C29BE403038D54FCAB411741C0 + +Count = 1065 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 0001020304050607 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B123A0EA9636AB0F96B5C8397B2F9B28D + +Count = 1066 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B4A49875F1844E384C868D30131350F7F + +Count = 1067 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 00010203040506070809 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BE62E99051D801AF82A944F5DC545C3E9 + +Count = 1068 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BD4A46279A8A000A4AA77ED2882C2F4E2 + +Count = 1069 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B36E9DF1545C4B8ECFB99CC7E5062BADE + +Count = 1070 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B9BE7050EC141C254BE8C91B097E70587 + +Count = 1071 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B9E947B7136C0AA67320708F23FDD5281 + +Count = 1072 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B1AC522C3BDEF3C5B71C9A1426AD5F48D + +Count = 1073 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BD4185160F5ED88930E22F46AF414BEA1 + +Count = 1074 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B0F97287F1535F1C3ADFB5FC55BC05AE3 + +Count = 1075 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BC77433961DC9C3B9921DEA7D023C0767 + +Count = 1076 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B34CFD3A806C74A813388F8AD3FF4F8C7 + +Count = 1077 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B654F40A547EE69F11409332357B700AE + +Count = 1078 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B377F930C72384B3D79130E741BE305AB + +Count = 1079 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B32B1EE63CCF39EBAAAF1E9845EC03428 + +Count = 1080 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B1A47B2427EC1F133ADB296F8D74276B7 + +Count = 1081 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B78EDCD520DAEE34C59B7C6E11F9A55D9 + +Count = 1082 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B3060CD6C0CCCDF5A83DFE4685E31647D + +Count = 1083 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F10111213141516171819 +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BFF42E4A548BDACDBE4E16DBB5F157BE2 + +Count = 1084 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B8EBA7874CCB6A35CFE446E6873FD3F57 + +Count = 1085 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BB7F91EDF1876D69F3CF663F10A38AC79 + +Count = 1086 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B8727CADBED5E9BAA865DA045778855C0 + +Count = 1087 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BDF5C64BF14085D85889697478759587F + +Count = 1088 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5BE9A219A89846E6396DDE3AF29F0425DE + +Count = 1089 +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 000102030405060708090A0B +PT = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +CT = 75F8BD7F4702EA535A1CE23E2D079F7B629979A2403D9F6F9CBA259DAB6F7E5B76604A0135D48F2C59D38E2B0072703F + diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.c b/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/api.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.c b/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.c new file mode 100644 index 0000000..770f568 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.c @@ -0,0 +1,881 @@ +/* + * 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 "elephant.h" +#include "internal-keccak.h" +#include "internal-spongent.h" +#include + +aead_cipher_t const dumbo_cipher = { + "Dumbo", + DUMBO_KEY_SIZE, + DUMBO_NONCE_SIZE, + DUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + dumbo_aead_encrypt, + dumbo_aead_decrypt +}; + +aead_cipher_t const jumbo_cipher = { + "Jumbo", + JUMBO_KEY_SIZE, + JUMBO_NONCE_SIZE, + JUMBO_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + jumbo_aead_encrypt, + jumbo_aead_decrypt +}; + +aead_cipher_t const delirium_cipher = { + "Delirium", + DELIRIUM_KEY_SIZE, + DELIRIUM_NONCE_SIZE, + DELIRIUM_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + delirium_aead_encrypt, + delirium_aead_decrypt +}; + +/** + * \brief Applies the Dumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void dumbo_lfsr + (unsigned char out[SPONGENT160_STATE_SIZE], + const unsigned char in[SPONGENT160_STATE_SIZE]) +{ + unsigned char temp = + leftRotate3_8(in[0]) ^ (in[3] << 7) ^ (in[13] >> 7); + unsigned index; + for (index = 0; index < SPONGENT160_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT160_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Dumbo. + * + * \param state Points to the Spongent-pi[160] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void dumbo_process_ad + (spongent160_state_t *state, + unsigned char mask[SPONGENT160_STATE_SIZE], + unsigned char next[SPONGENT160_STATE_SIZE], + unsigned char tag[DUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + dumbo_lfsr(next, mask); + dumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state->B, npub, DUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT160_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); + dumbo_lfsr(mask, mask); + dumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT160_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent160_permute(state); + lw_xor_block(state->B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state->B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, DUMBO_TAG_SIZE); +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT160_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, SPONGENT160_STATE_SIZE); + + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + mlen -= SPONGENT160_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + dumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT160_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + c += temp; + } else if (*clen != DUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DUMBO_TAG_SIZE); + return 0; +} + +int dumbo_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) +{ + spongent160_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT160_STATE_SIZE]; + unsigned char mask[SPONGENT160_STATE_SIZE]; + unsigned char next[SPONGENT160_STATE_SIZE]; + unsigned char tag[DUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DUMBO_TAG_SIZE) + return -1; + *mlen = clen - DUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DUMBO_KEY_SIZE); + memset(state.B + DUMBO_KEY_SIZE, 0, sizeof(state.B) - DUMBO_KEY_SIZE); + spongent160_permute(&state); + memcpy(mask, state.B, DUMBO_KEY_SIZE); + memset(mask + DUMBO_KEY_SIZE, 0, sizeof(mask) - DUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + dumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DUMBO_TAG_SIZE; + while (clen >= SPONGENT160_STATE_SIZE) { + /* Authenticate using the next mask */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT160_STATE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT160_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT160_STATE_SIZE); + c += SPONGENT160_STATE_SIZE; + m += SPONGENT160_STATE_SIZE; + clen -= SPONGENT160_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT160_STATE_SIZE); + lw_xor_block(state.B, npub, DUMBO_NONCE_SIZE); + spongent160_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + dumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT160_STATE_SIZE); + state.B[0] ^= 0x01; + spongent160_permute(&state); + lw_xor_block(state.B, mask, DUMBO_TAG_SIZE); + lw_xor_block(state.B, next, DUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, DUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Jumbo LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void jumbo_lfsr + (unsigned char out[SPONGENT176_STATE_SIZE], + const unsigned char in[SPONGENT176_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ (in[3] << 7) ^ (in[19] >> 7); + unsigned index; + for (index = 0; index < SPONGENT176_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[SPONGENT176_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Jumbo. + * + * \param state Points to the Spongent-pi[170] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void jumbo_process_ad + (spongent176_state_t *state, + unsigned char mask[SPONGENT176_STATE_SIZE], + unsigned char next[SPONGENT176_STATE_SIZE], + unsigned char tag[JUMBO_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + jumbo_lfsr(next, mask); + jumbo_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state->B, npub, JUMBO_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = JUMBO_NONCE_SIZE; + while (adlen > 0) { + size = SPONGENT176_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); + jumbo_lfsr(mask, mask); + jumbo_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, SPONGENT176_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + spongent176_permute(state); + lw_xor_block(state->B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state->B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state->B, JUMBO_TAG_SIZE); +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= SPONGENT176_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, SPONGENT176_STATE_SIZE); + + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + mlen -= SPONGENT176_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + jumbo_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, SPONGENT176_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, next, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + c += temp; + } else if (*clen != JUMBO_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, JUMBO_TAG_SIZE); + return 0; +} + +int jumbo_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) +{ + spongent176_state_t state; + unsigned char *mtemp = m; + unsigned char start[SPONGENT176_STATE_SIZE]; + unsigned char mask[SPONGENT176_STATE_SIZE]; + unsigned char next[SPONGENT176_STATE_SIZE]; + unsigned char tag[JUMBO_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < JUMBO_TAG_SIZE) + return -1; + *mlen = clen - JUMBO_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, JUMBO_KEY_SIZE); + memset(state.B + JUMBO_KEY_SIZE, 0, sizeof(state.B) - JUMBO_KEY_SIZE); + spongent176_permute(&state); + memcpy(mask, state.B, JUMBO_KEY_SIZE); + memset(mask + JUMBO_KEY_SIZE, 0, sizeof(mask) - JUMBO_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + jumbo_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= JUMBO_TAG_SIZE; + while (clen >= SPONGENT176_STATE_SIZE) { + /* Authenticate using the next mask */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, SPONGENT176_STATE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, SPONGENT176_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, SPONGENT176_STATE_SIZE); + c += SPONGENT176_STATE_SIZE; + m += SPONGENT176_STATE_SIZE; + clen -= SPONGENT176_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, SPONGENT176_STATE_SIZE); + lw_xor_block(state.B, npub, JUMBO_NONCE_SIZE); + spongent176_permute(&state); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + jumbo_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, SPONGENT176_STATE_SIZE); + state.B[0] ^= 0x01; + spongent176_permute(&state); + lw_xor_block(state.B, mask, JUMBO_TAG_SIZE); + lw_xor_block(state.B, next, JUMBO_TAG_SIZE); + lw_xor_block(tag, state.B, JUMBO_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, JUMBO_TAG_SIZE); +} + +/** + * \brief Applies the Delirium LFSR to the mask. + * + * \param out The output mask. + * \param in The input mask. + */ +static void delirium_lfsr + (unsigned char out[KECCAKP_200_STATE_SIZE], + const unsigned char in[KECCAKP_200_STATE_SIZE]) +{ + unsigned char temp = + leftRotate1_8(in[0]) ^ leftRotate1_8(in[2]) ^ (in[13] << 1); + unsigned index; + for (index = 0; index < KECCAKP_200_STATE_SIZE - 1; ++index) + out[index] = in[index + 1]; + out[KECCAKP_200_STATE_SIZE - 1] = temp; +} + +/** + * \brief Processes the nonce and associated data for Delirium. + * + * \param state Points to the Keccak[200] state. + * \param mask Points to the initial mask value. + * \param next Points to the next mask value. + * \param tag Points to the ongoing tag that is being computed. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void delirium_process_ad + (keccakp_200_state_t *state, + unsigned char mask[KECCAKP_200_STATE_SIZE], + unsigned char next[KECCAKP_200_STATE_SIZE], + unsigned char tag[DELIRIUM_TAG_SIZE], + const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned posn, size; + + /* We need the "previous" and "next" masks in each step. + * Compare the first such values */ + delirium_lfsr(next, mask); + delirium_lfsr(next, next); + + /* Absorb the nonce into the state */ + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state->B, npub, DELIRIUM_NONCE_SIZE); + + /* Absorb the rest of the associated data */ + posn = DELIRIUM_NONCE_SIZE; + while (adlen > 0) { + size = KECCAKP_200_STATE_SIZE - posn; + if (size <= adlen) { + /* Process a complete block */ + lw_xor_block(state->B + posn, ad, size); + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); + delirium_lfsr(mask, mask); + delirium_lfsr(next, next); + lw_xor_block_2_src(state->B, mask, next, KECCAKP_200_STATE_SIZE); + posn = 0; + } else { + /* Process the partial block at the end of the associated data */ + size = (unsigned)adlen; + lw_xor_block(state->B + posn, ad, size); + posn += size; + } + ad += size; + adlen -= size; + } + + /* Pad and absorb the final block */ + state->B[posn] ^= 0x01; + keccakp_200_permute(state, 18); + lw_xor_block(state->B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state->B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state->B, DELIRIUM_TAG_SIZE); +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Encrypt and authenticate the payload */ + while (mlen >= KECCAKP_200_STATE_SIZE) { + /* Encrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, KECCAKP_200_STATE_SIZE); + + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + mlen -= KECCAKP_200_STATE_SIZE; + } + if (mlen > 0) { + /* Encrypt the last block using the current mask */ + unsigned temp = (unsigned)mlen; + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, m, temp); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + memcpy(c, state.B, temp); + + /* Authenticate the last block using the next mask */ + delirium_lfsr(next, mask); + state.B[temp] = 0x01; + memset(state.B + temp + 1, 0, KECCAKP_200_STATE_SIZE - temp - 1); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, next, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + c += temp; + } else if (*clen != DELIRIUM_TAG_SIZE) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Generate the authentication tag */ + memcpy(c, tag, DELIRIUM_TAG_SIZE); + return 0; +} + +int delirium_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) +{ + keccakp_200_state_t state; + unsigned char *mtemp = m; + unsigned char start[KECCAKP_200_STATE_SIZE]; + unsigned char mask[KECCAKP_200_STATE_SIZE]; + unsigned char next[KECCAKP_200_STATE_SIZE]; + unsigned char tag[DELIRIUM_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < DELIRIUM_TAG_SIZE) + return -1; + *mlen = clen - DELIRIUM_TAG_SIZE; + + /* Hash the key and generate the initial mask */ + memcpy(state.B, k, DELIRIUM_KEY_SIZE); + memset(state.B + DELIRIUM_KEY_SIZE, 0, sizeof(state.B) - DELIRIUM_KEY_SIZE); + keccakp_200_permute(&state, 18); + memcpy(mask, state.B, DELIRIUM_KEY_SIZE); + memset(mask + DELIRIUM_KEY_SIZE, 0, sizeof(mask) - DELIRIUM_KEY_SIZE); + memcpy(start, mask, sizeof(mask)); + + /* Tag starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Authenticate the nonce and the associated data */ + delirium_process_ad(&state, mask, next, tag, npub, ad, adlen); + + /* Reset back to the starting mask for the encryption phase */ + memcpy(mask, start, sizeof(mask)); + + /* Decrypt and authenticate the payload */ + clen -= DELIRIUM_TAG_SIZE; + while (clen >= KECCAKP_200_STATE_SIZE) { + /* Authenticate using the next mask */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, KECCAKP_200_STATE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block_2_src(m, state.B, c, KECCAKP_200_STATE_SIZE); + + /* Advance to the next block */ + memcpy(mask, next, KECCAKP_200_STATE_SIZE); + c += KECCAKP_200_STATE_SIZE; + m += KECCAKP_200_STATE_SIZE; + clen -= KECCAKP_200_STATE_SIZE; + } + if (clen > 0) { + /* Authenticate the last block using the next mask */ + unsigned temp = (unsigned)clen; + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, c, temp); + state.B[temp] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + + /* Decrypt the last block using the current mask */ + memcpy(state.B, mask, KECCAKP_200_STATE_SIZE); + lw_xor_block(state.B, npub, DELIRIUM_NONCE_SIZE); + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, temp); + lw_xor_block_2_src(m, state.B, c, temp); + c += temp; + } else if (*mlen != 0) { + /* Pad and authenticate when the last block is aligned */ + delirium_lfsr(next, mask); + lw_xor_block_2_src(state.B, mask, next, KECCAKP_200_STATE_SIZE); + state.B[0] ^= 0x01; + keccakp_200_permute(&state, 18); + lw_xor_block(state.B, mask, DELIRIUM_TAG_SIZE); + lw_xor_block(state.B, next, DELIRIUM_TAG_SIZE); + lw_xor_block(tag, state.B, DELIRIUM_TAG_SIZE); + } + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, tag, c, DELIRIUM_TAG_SIZE); +} diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.h new file mode 100644 index 0000000..f775e3d --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/elephant.h @@ -0,0 +1,291 @@ +/* + * 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_ELEPHANT_H +#define LWCRYPTO_ELEPHANT_H + +#include "aead-common.h" + +/** + * \file elephant.h + * \brief Elephant authenticated encryption algorithm family. + * + * Elephant is a family of authenticated encryption algorithms based + * around the Spongent-pi and Keccak permutations. + * + * \li Dumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[160] permutation. This is + * the primary member of the family. + * \li Jumbo has a 128-bit key, a 96-bit nonce, and a 64-bit authentication + * tag. It is based around the Spongent-pi[176] permutation. + * \li Delirium has a 128-bit key, a 96-bit nonce, and a 128-bit authentication + * tag. It is based around the Keccak[200] permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Dumbo. + */ +#define DUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Dumbo. + */ +#define DUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Dumbo. + */ +#define DUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Jumbo. + */ +#define JUMBO_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Jumbo. + */ +#define JUMBO_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Jumbo. + */ +#define JUMBO_NONCE_SIZE 12 + +/** + * \brief Size of the key for Delirium. + */ +#define DELIRIUM_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Delirium. + */ +#define DELIRIUM_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Delirium. + */ +#define DELIRIUM_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Dumbo cipher. + */ +extern aead_cipher_t const dumbo_cipher; + +/** + * \brief Meta-information block for the Jumbo cipher. + */ +extern aead_cipher_t const jumbo_cipher; + +/** + * \brief Meta-information block for the Delirium cipher. + */ +extern aead_cipher_t const delirium_cipher; + +/** + * \brief Encrypts and authenticates a packet with Dumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa dumbo_aead_decrypt() + */ +int dumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Dumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa dumbo_aead_encrypt() + */ +int dumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Jumbo. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa jumbo_aead_decrypt() + */ +int jumbo_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); + +/** + * \brief Decrypts and authenticates a packet with Jumbo. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa jumbo_aead_encrypt() + */ +int jumbo_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); + +/** + * \brief Encrypts and authenticates a packet with Delirium. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa delirium_aead_decrypt() + */ +int delirium_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); + +/** + * \brief Decrypts and authenticates a packet with Delirium. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa delirium_aead_encrypt() + */ +int delirium_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/encrypt.c b/elephant/Implementations/crypto_aead/elephant200v1/rhys/encrypt.c new file mode 100644 index 0000000..bf6840c --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "elephant.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 delirium_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 delirium_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.c b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.c b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.c new file mode 100644 index 0000000..69a8ecb --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.c @@ -0,0 +1,346 @@ +/* + * 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 "internal-spongent.h" + +/** + * \brief Applies the Spongent-pi S-box in parallel to the 8 nibbles + * of a 32-bit word. + * + * \param x3 The input values to the parallel S-boxes. + * + * \return The output values from the parallel S-boxes. + * + * Based on the bit-sliced S-box implementation from here: + * https://github.com/DadaIsCrazy/usuba/blob/master/data/sboxes/spongent.ua + * + * Note that spongent.ua numbers bits from highest to lowest, so x0 is the + * high bit of each nibble and x3 is the low bit. + */ +static uint32_t spongent_sbox(uint32_t x3) +{ + uint32_t q0, q1, q2, q3, t0, t1, t2, t3; + uint32_t x2 = (x3 >> 1); + uint32_t x1 = (x2 >> 1); + uint32_t x0 = (x1 >> 1); + q0 = x0 ^ x2; + q1 = x1 ^ x2; + t0 = q0 & q1; + q2 = ~(x0 ^ x1 ^ x3 ^ t0); + t1 = q2 & ~x0; + q3 = x1 ^ t1; + t2 = q3 & (q3 ^ x2 ^ x3 ^ t0); + t3 = (x2 ^ t0) & ~(x1 ^ t0); + q0 = x1 ^ x2 ^ x3 ^ t2; + q1 = x0 ^ x2 ^ x3 ^ t0 ^ t1; + q2 = x0 ^ x1 ^ x2 ^ t1; + q3 = x0 ^ x3 ^ t0 ^ t3; + return ((q0 << 3) & 0x88888888U) | ((q1 << 2) & 0x44444444U) | + ((q2 << 1) & 0x22222222U) | (q3 & 0x11111111U); +} + +void spongent160_permute(spongent160_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[160] */ + 0x75, 0xae, 0x6a, 0x56, 0x54, 0x2a, 0x29, 0x94, + 0x53, 0xca, 0x27, 0xe4, 0x4f, 0xf2, 0x1f, 0xf8, + 0x3e, 0x7c, 0x7d, 0xbe, 0x7a, 0x5e, 0x74, 0x2e, + 0x68, 0x16, 0x50, 0x0a, 0x21, 0x84, 0x43, 0xc2, + 0x07, 0xe0, 0x0e, 0x70, 0x1c, 0x38, 0x38, 0x1c, + 0x71, 0x8e, 0x62, 0x46, 0x44, 0x22, 0x09, 0x90, + 0x12, 0x48, 0x24, 0x24, 0x49, 0x92, 0x13, 0xc8, + 0x26, 0x64, 0x4d, 0xb2, 0x1b, 0xd8, 0x36, 0x6c, + 0x6d, 0xb6, 0x5a, 0x5a, 0x35, 0xac, 0x6b, 0xd6, + 0x56, 0x6a, 0x2d, 0xb4, 0x5b, 0xda, 0x37, 0xec, + 0x6f, 0xf6, 0x5e, 0x7a, 0x3d, 0xbc, 0x7b, 0xde, + 0x76, 0x6e, 0x6c, 0x36, 0x58, 0x1a, 0x31, 0x8c, + 0x63, 0xc6, 0x46, 0x62, 0x0d, 0xb0, 0x1a, 0x58, + 0x34, 0x2c, 0x69, 0x96, 0x52, 0x4a, 0x25, 0xa4, + 0x4b, 0xd2, 0x17, 0xe8, 0x2e, 0x74, 0x5d, 0xba, + 0x3b, 0xdc, 0x77, 0xee, 0x6e, 0x76, 0x5c, 0x3a, + 0x39, 0x9c, 0x73, 0xce, 0x66, 0x66, 0x4c, 0x32, + 0x19, 0x98, 0x32, 0x4c, 0x65, 0xa6, 0x4a, 0x52, + 0x15, 0xa8, 0x2a, 0x54, 0x55, 0xaa, 0x2b, 0xd4, + 0x57, 0xea, 0x2f, 0xf4, 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4; + uint32_t t0, t1, t2, t3, t4; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); +#endif + + /* Perform the 80 rounds of Spongent-pi[160] */ + for (round = 0; round < 80; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x4 ^= ((uint32_t)(rc[1])) << 24; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + + /* Permute the bits of the state. Bit i is moved to (40 * i) % 159 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + #define BCP(x, bit) ((x) & (((uint32_t)1) << (bit))) + #define BUP(x, from, to) \ + (((x) << ((to) - (from))) & (((uint32_t)1) << (to))) + #define BDN(x, from, to) \ + (((x) >> ((from) - (to))) & (((uint32_t)1) << (to))) + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 8) ^ BUP(t0, 5, 9) ^ BUP(t0, 9, 10) ^ + BDN(t0, 13, 11) ^ BDN(t0, 17, 12) ^ BDN(t0, 21, 13) ^ + BDN(t0, 25, 14) ^ BDN(t0, 29, 15) ^ BUP(t1, 1, 16) ^ + BUP(t1, 5, 17) ^ BUP(t1, 9, 18) ^ BUP(t1, 13, 19) ^ + BUP(t1, 17, 20) ^ BCP(t1, 21) ^ BDN(t1, 25, 22) ^ + BDN(t1, 29, 23) ^ BUP(t2, 1, 24) ^ BUP(t2, 5, 25) ^ + BUP(t2, 9, 26) ^ BUP(t2, 13, 27) ^ BUP(t2, 17, 28) ^ + BUP(t2, 21, 29) ^ BUP(t2, 25, 30) ^ BUP(t2, 29, 31) ^ + BCP(t4, 0) ^ BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ + BDN(t4, 12, 3) ^ BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ + BDN(t4, 24, 6) ^ BDN(t4, 28, 7); + x2 = BUP(t0, 2, 16) ^ BUP(t0, 6, 17) ^ BUP(t0, 10, 18) ^ + BUP(t0, 14, 19) ^ BUP(t0, 18, 20) ^ BDN(t0, 22, 21) ^ + BDN(t0, 26, 22) ^ BDN(t0, 30, 23) ^ BUP(t1, 2, 24) ^ + BUP(t1, 6, 25) ^ BUP(t1, 10, 26) ^ BUP(t1, 14, 27) ^ + BUP(t1, 18, 28) ^ BUP(t1, 22, 29) ^ BUP(t1, 26, 30) ^ + BUP(t1, 30, 31) ^ BDN(t3, 1, 0) ^ BDN(t3, 5, 1) ^ + BDN(t3, 9, 2) ^ BDN(t3, 13, 3) ^ BDN(t3, 17, 4) ^ + BDN(t3, 21, 5) ^ BDN(t3, 25, 6) ^ BDN(t3, 29, 7) ^ + BUP(t4, 1, 8) ^ BUP(t4, 5, 9) ^ BUP(t4, 9, 10) ^ + BDN(t4, 13, 11) ^ BDN(t4, 17, 12) ^ BDN(t4, 21, 13) ^ + BDN(t4, 25, 14) ^ BDN(t4, 29, 15); + x3 = BUP(t0, 3, 24) ^ BUP(t0, 7, 25) ^ BUP(t0, 11, 26) ^ + BUP(t0, 15, 27) ^ BUP(t0, 19, 28) ^ BUP(t0, 23, 29) ^ + BUP(t0, 27, 30) ^ BCP(t0, 31) ^ BDN(t2, 2, 0) ^ + BDN(t2, 6, 1) ^ BDN(t2, 10, 2) ^ BDN(t2, 14, 3) ^ + BDN(t2, 18, 4) ^ BDN(t2, 22, 5) ^ BDN(t2, 26, 6) ^ + BDN(t2, 30, 7) ^ BUP(t3, 2, 8) ^ BUP(t3, 6, 9) ^ + BCP(t3, 10) ^ BDN(t3, 14, 11) ^ BDN(t3, 18, 12) ^ + BDN(t3, 22, 13) ^ BDN(t3, 26, 14) ^ BDN(t3, 30, 15) ^ + BUP(t4, 2, 16) ^ BUP(t4, 6, 17) ^ BUP(t4, 10, 18) ^ + BUP(t4, 14, 19) ^ BUP(t4, 18, 20) ^ BDN(t4, 22, 21) ^ + BDN(t4, 26, 22) ^ BDN(t4, 30, 23); + x4 = BDN(t1, 3, 0) ^ BDN(t1, 7, 1) ^ BDN(t1, 11, 2) ^ + BDN(t1, 15, 3) ^ BDN(t1, 19, 4) ^ BDN(t1, 23, 5) ^ + BDN(t1, 27, 6) ^ BDN(t1, 31, 7) ^ BUP(t2, 3, 8) ^ + BUP(t2, 7, 9) ^ BDN(t2, 11, 10) ^ BDN(t2, 15, 11) ^ + BDN(t2, 19, 12) ^ BDN(t2, 23, 13) ^ BDN(t2, 27, 14) ^ + BDN(t2, 31, 15) ^ BUP(t3, 3, 16) ^ BUP(t3, 7, 17) ^ + BUP(t3, 11, 18) ^ BUP(t3, 15, 19) ^ BUP(t3, 19, 20) ^ + BDN(t3, 23, 21) ^ BDN(t3, 27, 22) ^ BDN(t3, 31, 23) ^ + BUP(t4, 3, 24) ^ BUP(t4, 7, 25) ^ BUP(t4, 11, 26) ^ + BUP(t4, 15, 27) ^ BUP(t4, 19, 28) ^ BUP(t4, 23, 29) ^ + BUP(t4, 27, 30) ^ BCP(t4, 31); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); +#endif +} + +void spongent176_permute(spongent176_state_t *state) +{ + static uint8_t const RC[] = { + /* Round constants for Spongent-pi[176] */ + 0x45, 0xa2, 0x0b, 0xd0, 0x16, 0x68, 0x2c, 0x34, + 0x59, 0x9a, 0x33, 0xcc, 0x67, 0xe6, 0x4e, 0x72, + 0x1d, 0xb8, 0x3a, 0x5c, 0x75, 0xae, 0x6a, 0x56, + 0x54, 0x2a, 0x29, 0x94, 0x53, 0xca, 0x27, 0xe4, + 0x4f, 0xf2, 0x1f, 0xf8, 0x3e, 0x7c, 0x7d, 0xbe, + 0x7a, 0x5e, 0x74, 0x2e, 0x68, 0x16, 0x50, 0x0a, + 0x21, 0x84, 0x43, 0xc2, 0x07, 0xe0, 0x0e, 0x70, + 0x1c, 0x38, 0x38, 0x1c, 0x71, 0x8e, 0x62, 0x46, + 0x44, 0x22, 0x09, 0x90, 0x12, 0x48, 0x24, 0x24, + 0x49, 0x92, 0x13, 0xc8, 0x26, 0x64, 0x4d, 0xb2, + 0x1b, 0xd8, 0x36, 0x6c, 0x6d, 0xb6, 0x5a, 0x5a, + 0x35, 0xac, 0x6b, 0xd6, 0x56, 0x6a, 0x2d, 0xb4, + 0x5b, 0xda, 0x37, 0xec, 0x6f, 0xf6, 0x5e, 0x7a, + 0x3d, 0xbc, 0x7b, 0xde, 0x76, 0x6e, 0x6c, 0x36, + 0x58, 0x1a, 0x31, 0x8c, 0x63, 0xc6, 0x46, 0x62, + 0x0d, 0xb0, 0x1a, 0x58, 0x34, 0x2c, 0x69, 0x96, + 0x52, 0x4a, 0x25, 0xa4, 0x4b, 0xd2, 0x17, 0xe8, + 0x2e, 0x74, 0x5d, 0xba, 0x3b, 0xdc, 0x77, 0xee, + 0x6e, 0x76, 0x5c, 0x3a, 0x39, 0x9c, 0x73, 0xce, + 0x66, 0x66, 0x4c, 0x32, 0x19, 0x98, 0x32, 0x4c, + 0x65, 0xa6, 0x4a, 0x52, 0x15, 0xa8, 0x2a, 0x54, + 0x55, 0xaa, 0x2b, 0xd4, 0x57, 0xea, 0x2f, 0xf4, + 0x5f, 0xfa, 0x3f, 0xfc + }; + const uint8_t *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t t0, t1, t2, t3, t4, t5; + uint8_t round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = state->W[0]; + x1 = state->W[1]; + x2 = state->W[2]; + x3 = state->W[3]; + x4 = state->W[4]; + x5 = state->W[5]; +#else + x0 = le_load_word32(state->B); + x1 = le_load_word32(state->B + 4); + x2 = le_load_word32(state->B + 8); + x3 = le_load_word32(state->B + 12); + x4 = le_load_word32(state->B + 16); + x5 = le_load_word16(state->B + 20); /* Last word is only 16 bits */ +#endif + + /* Perform the 90 rounds of Spongent-pi[176] */ + for (round = 0; round < 90; ++round, rc += 2) { + /* Add the round constant to front and back of the state */ + x0 ^= rc[0]; + x5 ^= ((uint32_t)(rc[1])) << 8; + + /* Apply the S-box to all 4-bit groups in the state */ + t0 = spongent_sbox(x0); + t1 = spongent_sbox(x1); + t2 = spongent_sbox(x2); + t3 = spongent_sbox(x3); + t4 = spongent_sbox(x4); + t5 = spongent_sbox(x5); + + /* Permute the bits of the state. Bit i is moved to (44 * i) % 175 + * for all bits except the last which is left where it is. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + x0 = BCP(t0, 0) ^ BDN(t0, 4, 1) ^ BDN(t0, 8, 2) ^ + BDN(t0, 12, 3) ^ BDN(t0, 16, 4) ^ BDN(t0, 20, 5) ^ + BDN(t0, 24, 6) ^ BDN(t0, 28, 7) ^ BUP(t1, 0, 8) ^ + BUP(t1, 4, 9) ^ BUP(t1, 8, 10) ^ BDN(t1, 12, 11) ^ + BDN(t1, 16, 12) ^ BDN(t1, 20, 13) ^ BDN(t1, 24, 14) ^ + BDN(t1, 28, 15) ^ BUP(t2, 0, 16) ^ BUP(t2, 4, 17) ^ + BUP(t2, 8, 18) ^ BUP(t2, 12, 19) ^ BUP(t2, 16, 20) ^ + BUP(t2, 20, 21) ^ BDN(t2, 24, 22) ^ BDN(t2, 28, 23) ^ + BUP(t3, 0, 24) ^ BUP(t3, 4, 25) ^ BUP(t3, 8, 26) ^ + BUP(t3, 12, 27) ^ BUP(t3, 16, 28) ^ BUP(t3, 20, 29) ^ + BUP(t3, 24, 30) ^ BUP(t3, 28, 31); + x1 = BUP(t0, 1, 12) ^ BUP(t0, 5, 13) ^ BUP(t0, 9, 14) ^ + BUP(t0, 13, 15) ^ BDN(t0, 17, 16) ^ BDN(t0, 21, 17) ^ + BDN(t0, 25, 18) ^ BDN(t0, 29, 19) ^ BUP(t1, 1, 20) ^ + BUP(t1, 5, 21) ^ BUP(t1, 9, 22) ^ BUP(t1, 13, 23) ^ + BUP(t1, 17, 24) ^ BUP(t1, 21, 25) ^ BUP(t1, 25, 26) ^ + BDN(t1, 29, 27) ^ BUP(t2, 1, 28) ^ BUP(t2, 5, 29) ^ + BUP(t2, 9, 30) ^ BUP(t2, 13, 31) ^ BCP(t4, 0) ^ + BDN(t4, 4, 1) ^ BDN(t4, 8, 2) ^ BDN(t4, 12, 3) ^ + BDN(t4, 16, 4) ^ BDN(t4, 20, 5) ^ BDN(t4, 24, 6) ^ + BDN(t4, 28, 7) ^ BUP(t5, 0, 8) ^ BUP(t5, 4, 9) ^ + BUP(t5, 8, 10) ^ BDN(t5, 12, 11); + x2 = BUP(t0, 2, 24) ^ BUP(t0, 6, 25) ^ BUP(t0, 10, 26) ^ + BUP(t0, 14, 27) ^ BUP(t0, 18, 28) ^ BUP(t0, 22, 29) ^ + BUP(t0, 26, 30) ^ BUP(t0, 30, 31) ^ BDN(t2, 17, 0) ^ + BDN(t2, 21, 1) ^ BDN(t2, 25, 2) ^ BDN(t2, 29, 3) ^ + BUP(t3, 1, 4) ^ BCP(t3, 5) ^ BDN(t3, 9, 6) ^ + BDN(t3, 13, 7) ^ BDN(t3, 17, 8) ^ BDN(t3, 21, 9) ^ + BDN(t3, 25, 10) ^ BDN(t3, 29, 11) ^ BUP(t4, 1, 12) ^ + BUP(t4, 5, 13) ^ BUP(t4, 9, 14) ^ BUP(t4, 13, 15) ^ + BDN(t4, 17, 16) ^ BDN(t4, 21, 17) ^ BDN(t4, 25, 18) ^ + BDN(t4, 29, 19) ^ BUP(t5, 1, 20) ^ BUP(t5, 5, 21) ^ + BUP(t5, 9, 22) ^ BUP(t5, 13, 23); + x3 = BDN(t1, 2, 0) ^ BDN(t1, 6, 1) ^ BDN(t1, 10, 2) ^ + BDN(t1, 14, 3) ^ BDN(t1, 18, 4) ^ BDN(t1, 22, 5) ^ + BDN(t1, 26, 6) ^ BDN(t1, 30, 7) ^ BUP(t2, 2, 8) ^ + BUP(t2, 6, 9) ^ BCP(t2, 10) ^ BDN(t2, 14, 11) ^ + BDN(t2, 18, 12) ^ BDN(t2, 22, 13) ^ BDN(t2, 26, 14) ^ + BDN(t2, 30, 15) ^ BUP(t3, 2, 16) ^ BUP(t3, 6, 17) ^ + BUP(t3, 10, 18) ^ BUP(t3, 14, 19) ^ BUP(t3, 18, 20) ^ + BDN(t3, 22, 21) ^ BDN(t3, 26, 22) ^ BDN(t3, 30, 23) ^ + BUP(t4, 2, 24) ^ BUP(t4, 6, 25) ^ BUP(t4, 10, 26) ^ + BUP(t4, 14, 27) ^ BUP(t4, 18, 28) ^ BUP(t4, 22, 29) ^ + BUP(t4, 26, 30) ^ BUP(t4, 30, 31); + x4 = BUP(t0, 3, 4) ^ BDN(t0, 7, 5) ^ BDN(t0, 11, 6) ^ + BDN(t0, 15, 7) ^ BDN(t0, 19, 8) ^ BDN(t0, 23, 9) ^ + BDN(t0, 27, 10) ^ BDN(t0, 31, 11) ^ BUP(t1, 3, 12) ^ + BUP(t1, 7, 13) ^ BUP(t1, 11, 14) ^ BCP(t1, 15) ^ + BDN(t1, 19, 16) ^ BDN(t1, 23, 17) ^ BDN(t1, 27, 18) ^ + BDN(t1, 31, 19) ^ BUP(t2, 3, 20) ^ BUP(t2, 7, 21) ^ + BUP(t2, 11, 22) ^ BUP(t2, 15, 23) ^ BUP(t2, 19, 24) ^ + BUP(t2, 23, 25) ^ BDN(t2, 27, 26) ^ BDN(t2, 31, 27) ^ + BUP(t3, 3, 28) ^ BUP(t3, 7, 29) ^ BUP(t3, 11, 30) ^ + BUP(t3, 15, 31) ^ BDN(t5, 2, 0) ^ BDN(t5, 6, 1) ^ + BDN(t5, 10, 2) ^ BDN(t5, 14, 3); + x5 = BDN(t3, 19, 0) ^ BDN(t3, 23, 1) ^ BDN(t3, 27, 2) ^ + BDN(t3, 31, 3) ^ BUP(t4, 3, 4) ^ BDN(t4, 7, 5) ^ + BDN(t4, 11, 6) ^ BDN(t4, 15, 7) ^ BDN(t4, 19, 8) ^ + BDN(t4, 23, 9) ^ BDN(t4, 27, 10) ^ BDN(t4, 31, 11) ^ + BUP(t5, 3, 12) ^ BUP(t5, 7, 13) ^ BUP(t5, 11, 14) ^ + BCP(t5, 15); + } + + /* Store the local variables back to the state in little-endian order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = x0; + state->W[1] = x1; + state->W[2] = x2; + state->W[3] = x3; + state->W[4] = x4; + state->W[5] = x5; +#else + le_store_word32(state->B, x0); + le_store_word32(state->B + 4, x1); + le_store_word32(state->B + 8, x2); + le_store_word32(state->B + 12, x3); + le_store_word32(state->B + 16, x4); + le_store_word16(state->B + 20, x5); /* Last word is only 16 bits */ +#endif +} diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.h new file mode 100644 index 0000000..bb9823f --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-spongent.h @@ -0,0 +1,91 @@ +/* + * 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_SPONGENT_H +#define LW_INTERNAL_SPONGENT_H + +#include "internal-util.h" + +/** + * \file internal-spongent.h + * \brief Internal implementation of the Spongent-pi permutation. + * + * References: https://www.esat.kuleuven.be/cosic/elephant/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the Spongent-pi[160] state in bytes. + */ +#define SPONGENT160_STATE_SIZE 20 + +/** + * \brief Size of the Spongent-pi[176] state in bytes. + */ +#define SPONGENT176_STATE_SIZE 22 + +/** + * \brief Structure of the internal state of the Spongent-pi[160] permutation. + */ +typedef union +{ + uint32_t W[5]; /**< Spongent-pi[160] state as 32-bit words */ + uint8_t B[20]; /**< Spongent-pi[160] state as bytes */ + +} spongent160_state_t; + +/** + * \brief Structure of the internal state of the Spongent-pi[176] permutation. + * + * Note: The state is technically only 176 bits, but we increase it to + * 192 bits so that we can use 32-bit word operations to manipulate the + * state. The extra bits in the last word are fixed to zero. + */ +typedef union +{ + uint32_t W[6]; /**< Spongent-pi[176] state as 32-bit words */ + uint8_t B[24]; /**< Spongent-pi[176] state as bytes */ + +} spongent176_state_t; + +/** + * \brief Permutes the Spongent-pi[160] state. + * + * \param state The Spongent-pi[160] state to be permuted. + */ +void spongent160_permute(spongent160_state_t *state); + +/** + * \brief Permutes the Spongent-pi[176] state. + * + * \param state The Spongent-pi[176] state to be permuted. + */ +void spongent176_permute(spongent176_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-util.h b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/elephant/Implementations/crypto_aead/elephant200v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.c b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.h b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/api.h b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/encrypt.c b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/encrypt.c new file mode 100644 index 0000000..daa5139 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "estate.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 estate_twegift_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 estate_twegift_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.c b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.c new file mode 100644 index 0000000..355aa92 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.c @@ -0,0 +1,196 @@ +/* + * 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 "estate.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const estate_twegift_cipher = { + "ESTATE_TweGIFT-128", + ESTATE_TWEGIFT_KEY_SIZE, + ESTATE_TWEGIFT_NONCE_SIZE, + ESTATE_TWEGIFT_TAG_SIZE, + AEAD_FLAG_NONE, + estate_twegift_aead_encrypt, + estate_twegift_aead_decrypt +}; + +/** + * \brief Generates the FCBC MAC for a packet using ESTATE_TweGIFT-128. + * + * \param ks The key schedule for TweGIFT-128. + * \param tag Rolling state of the authentication tag. + * \param m Message to be authenticated. + * \param mlen Length of the message to be authenticated; must be >= 1. + * \param tweak1 Tweak value to use when the last block is full. + * \param tweak2 Tweak value to use when the last block is partial. + */ +static void estate_twegift_fcbc + (const gift128n_key_schedule_t *ks, unsigned char tag[16], + const unsigned char *m, unsigned long long mlen, + unsigned char tweak1, unsigned char tweak2) +{ + while (mlen > 16) { + lw_xor_block(tag, m, 16); + gift128n_encrypt(ks, tag, tag); + m += 16; + mlen -= 16; + } + if (mlen == 16) { + lw_xor_block(tag, m, 16); + gift128t_encrypt(ks, tag, tag, tweak1); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block(tag, m, temp); + tag[temp] ^= 0x01; + gift128t_encrypt(ks, tag, tag, tweak2); + } +} + +/** + * \brief Generates the MAC for a packet using ESTATE_TweGIFT-128. + * + * \param ks The key schedule for TweGIFT-128. + * \param tag Rolling state of the authentication tag. + * \param m Message to be authenticated. + * \param mlen Length of the message to be authenticated. + * \param ad Associated data to be authenticated. + * \param adlen Length of the associated data to be authenticated. + */ +static void estate_twegift_authenticate + (const gift128n_key_schedule_t *ks, unsigned char tag[16], + const unsigned char *m, unsigned long long mlen, + const unsigned char *ad, unsigned long long adlen) +{ + /* Handle the case where both the message and associated data are empty */ + if (mlen == 0 && adlen == 0) { + gift128t_encrypt(ks, tag, tag, /*tweak=*/8); + return; + } + + /* Encrypt the nonce */ + gift128t_encrypt(ks, tag, tag, /*tweak=*/1); + + /* Compute the FCBC MAC over the associated data */ + if (adlen != 0) { + if (mlen != 0) + estate_twegift_fcbc(ks, tag, ad, adlen, /*tweak1=*/2, /*tweak2=*/3); + else + estate_twegift_fcbc(ks, tag, ad, adlen, /*tweak1=*/6, /*tweak2=*/7); + } + + /* Compute the FCBC MAC over the message data */ + if (mlen != 0) + estate_twegift_fcbc(ks, tag, m, mlen, /*tweak1=*/4, /*tweak2=*/5); +} + +/** + * \brief Encrypts (or decrypts) a payload using ESTATE_TweGIFT-128. + * + * \param ks The key schedule for TweGIFT-128. + * \param tag Pre-computed authentication tag for the packet. + * \param c Ciphertext after encryption. + * \param m Plaintext to be encrypted. + * \param mlen Length of the plaintext to be encrypted. + */ +static void estate_twegift_encrypt + (const gift128n_key_schedule_t *ks, const unsigned char tag[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[16]; + memcpy(block, tag, 16); + while (mlen >= 16) { + gift128n_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, 16); + c += 16; + m += 16; + mlen -= 16; + } + if (mlen > 0) { + gift128n_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, (unsigned)mlen); + } +} + +int estate_twegift_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) +{ + gift128n_key_schedule_t ks; + unsigned char tag[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ESTATE_TWEGIFT_TAG_SIZE; + + /* Set up the key schedule and copy the nonce into the tag */ + if (!gift128n_init(&ks, k, ESTATE_TWEGIFT_KEY_SIZE)) + return -1; + memcpy(tag, npub, 16); + + /* Authenticate the associated data and plaintext */ + estate_twegift_authenticate(&ks, tag, m, mlen, ad, adlen); + + /* Encrypt the plaintext to generate the ciphertext */ + estate_twegift_encrypt(&ks, tag, c, m, mlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, tag, 16); + return 0; +} + +int estate_twegift_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) +{ + gift128n_key_schedule_t ks; + unsigned char tag[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ESTATE_TWEGIFT_TAG_SIZE) + return -1; + *mlen = clen - ESTATE_TWEGIFT_TAG_SIZE; + + /* Set up the key schedule and copy the nonce into the tag */ + if (!gift128n_init(&ks, k, ESTATE_TWEGIFT_KEY_SIZE)) + return -1; + memcpy(tag, npub, 16); + + /* Decrypt the ciphertext to generate the plaintext */ + estate_twegift_encrypt(&ks, c + *mlen, m, c, *mlen); + + /* Authenticate the associated data and plaintext */ + estate_twegift_authenticate(&ks, tag, m, *mlen, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, tag, c + *mlen, 16); +} diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.h b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.h new file mode 100644 index 0000000..d38ee16 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/estate.h @@ -0,0 +1,137 @@ +/* + * 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_ESTATE_H +#define LWCRYPTO_ESTATE_H + +#include "aead-common.h" + +/** + * \file estate.h + * \brief ESTATE authenticated encryption algorithm. + * + * ESTATE_TweGIFT-128 is an authenticated encryption algorithm with a + * 128-bit key, a 128-bit nonce, and a 128-bit tag. It is a two-pass + * algorithm that is built around a tweaked version of the GIFT-128 block + * cipher, the FCBC authentication mode, and the OFB encryption mode. + * + * ESTATE is resistant against nonce reuse as long as the combination + * of the associated data and plaintext is unique. + * + * If a nonce is reused then two packets with the same nonce, associated data, + * and plaintext will encrypt to the same ciphertext. This will leak that + * the same plaintext has been sent for a second time but will not reveal + * the plaintext itself. + * + * The ESTATE family also includes variants build around tweaked versions + * of the AES block cipher. We do not implement those variants in this + * library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ESTATE_TweGIFT-128. + */ +#define ESTATE_TWEGIFT_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for ESTATE_TweGIFT-128. + */ +#define ESTATE_TWEGIFT_TAG_SIZE 16 + +/** + * \brief Size of the nonce for ESTATE_TweGIFT-128. + */ +#define ESTATE_TWEGIFT_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the ESTATE_TweGIFT-128 cipher. + */ +extern aead_cipher_t const estate_twegift_cipher; + +/** + * \brief Encrypts and authenticates a packet with ESTATE_TweGIFT-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa estate_twegift_aead_decrypt() + */ +int estate_twegift_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); + +/** + * \brief Decrypts and authenticates a packet with ESTATE_TweGIFT-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa estate_twegift_aead_encrypt() + */ +int estate_twegift_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.c b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.h b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-util.h b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/estate/Implementations/crypto_aead/estatetwegift128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/api.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/api.h new file mode 100644 index 0000000..3818b25 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 6 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/encrypt.c new file mode 100644 index 0000000..3741901 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_paef_128_192_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 forkae_paef_128_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t192n48v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/api.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/api.h new file mode 100644 index 0000000..6c701b5 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 14 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/encrypt.c new file mode 100644 index 0000000..be76f9b --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_paef_128_256_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 forkae_paef_128_256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t256n112v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/api.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/api.h new file mode 100644 index 0000000..500c2c7 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 13 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/encrypt.c new file mode 100644 index 0000000..b23be7f --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_paef_128_288_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 forkae_paef_128_288_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb128t288n104v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/api.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/api.h new file mode 100644 index 0000000..f04cc58 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 6 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/encrypt.c new file mode 100644 index 0000000..275b77e --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_paef_64_192_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 forkae_paef_64_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/paefforkskinnyb64t192n48v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/api.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/api.h new file mode 100644 index 0000000..40ffe7c --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 7 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/encrypt.c new file mode 100644 index 0000000..5cbb412 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_saef_128_192_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 forkae_saef_128_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t192n56v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/api.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/api.h new file mode 100644 index 0000000..86e276c --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 15 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/encrypt.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/encrypt.c new file mode 100644 index 0000000..7d59b31 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "forkae.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 forkae_saef_128_256_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 forkae_saef_128_256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.c new file mode 100644 index 0000000..4a9671a --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.c @@ -0,0 +1,140 @@ +/* + * 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 "forkae.h" +#include "internal-forkskinny.h" +#include "internal-util.h" +#include + +aead_cipher_t const forkae_paef_64_192_cipher = { + "PAEF-ForkSkinny-64-192", + FORKAE_PAEF_64_192_KEY_SIZE, + FORKAE_PAEF_64_192_NONCE_SIZE, + FORKAE_PAEF_64_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_64_192_aead_encrypt, + forkae_paef_64_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_192_cipher = { + "PAEF-ForkSkinny-128-192", + FORKAE_PAEF_128_192_KEY_SIZE, + FORKAE_PAEF_128_192_NONCE_SIZE, + FORKAE_PAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_192_aead_encrypt, + forkae_paef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_256_cipher = { + "PAEF-ForkSkinny-128-256", + FORKAE_PAEF_128_256_KEY_SIZE, + FORKAE_PAEF_128_256_NONCE_SIZE, + FORKAE_PAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_256_aead_encrypt, + forkae_paef_128_256_aead_decrypt +}; + +aead_cipher_t const forkae_paef_128_288_cipher = { + "PAEF-ForkSkinny-128-288", + FORKAE_PAEF_128_288_KEY_SIZE, + FORKAE_PAEF_128_288_NONCE_SIZE, + FORKAE_PAEF_128_288_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_paef_128_288_aead_encrypt, + forkae_paef_128_288_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_192_cipher = { + "SAEF-ForkSkinny-128-192", + FORKAE_SAEF_128_192_KEY_SIZE, + FORKAE_SAEF_128_192_NONCE_SIZE, + FORKAE_SAEF_128_192_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_192_aead_encrypt, + forkae_saef_128_192_aead_decrypt +}; + +aead_cipher_t const forkae_saef_128_256_cipher = { + "SAEF-ForkSkinny-128-256", + FORKAE_SAEF_128_256_KEY_SIZE, + FORKAE_SAEF_128_256_NONCE_SIZE, + FORKAE_SAEF_128_256_TAG_SIZE, + AEAD_FLAG_NONE, + forkae_saef_128_256_aead_encrypt, + forkae_saef_128_256_aead_decrypt +}; + +/* PAEF-ForkSkinny-64-192 */ +#define FORKAE_ALG_NAME forkae_paef_64_192 +#define FORKAE_BLOCK_SIZE 8 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_64_192 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_paef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_paef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 2 +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-paef.h" + +/* PAEF-ForkSkinny-128-288 */ +#define FORKAE_ALG_NAME forkae_paef_128_288 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE +#define FORKAE_COUNTER_SIZE 7 +#define FORKAE_TWEAKEY_SIZE 48 +#define FORKAE_BLOCK_FUNC forkskinny_128_384 +#include "internal-forkae-paef.h" + +/* SAEF-ForkSkinny-128-192 */ +#define FORKAE_ALG_NAME forkae_saef_128_192 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 24 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" + +/* SAEF-ForkSkinny-128-256 */ +#define FORKAE_ALG_NAME forkae_saef_128_256 +#define FORKAE_BLOCK_SIZE 16 +#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE +#define FORKAE_TWEAKEY_SIZE 32 +#define FORKAE_TWEAKEY_REDUCED_SIZE 32 +#define FORKAE_BLOCK_FUNC forkskinny_128_256 +#include "internal-forkae-saef.h" diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.h new file mode 100644 index 0000000..3e27b50 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/forkae.h @@ -0,0 +1,551 @@ +/* + * 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_FORKAE_H +#define LWCRYPTO_FORKAE_H + +#include "aead-common.h" + +/** + * \file forkae.h + * \brief ForkAE authenticated encryption algorithm family. + * + * ForkAE is a family of authenticated encryption algorithms based on a + * modified version of the SKINNY tweakable block cipher. The modifications + * introduce "forking" where each input block produces two output blocks + * for use in encryption and authentication. There are six members in + * the ForkAE family: + * + * \li PAEF-ForkSkinny-64-192 has a 128-bit key, a 48-bit nonce, and a + * 64-bit authentication tag. The associated data and plaintext are + * limited to 216 bytes. + * \li PAEF-ForkSkinny-128-192 has a 128-bit key, a 48-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-256 has a 128-bit key, a 112-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 217 bytes. + * \li PAEF-ForkSkinny-128-288 has a 128-bit key, a 104-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext are + * limited to 257 bytes. This is the primary member of the family. + * \li SAEF-ForkSkinny-128-192 has a 128-bit key, a 56-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * \li SAEF-ForkSkinny-128-256 has a 128-bit key, a 120-bit nonce, and a + * 128-bit authentication tag. The associated data and plaintext may be + * unlimited in size. + * + * The PAEF variants support parallel encryption and decryption for + * higher throughput. The SAEF variants encrypt or decrypt blocks + * sequentially. + * + * ForkAE is designed to be efficient on small packet sizes so most of + * the PAEF algorithms have a limit of 64k or 128k on the amount of + * payload in a single packet. Obviously the input can be split into + * separate packets for larger amounts of data. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_TAG_SIZE 8 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-64-192. + */ +#define FORKAE_PAEF_64_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-192. + */ +#define FORKAE_PAEF_128_192_NONCE_SIZE 6 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-256. + */ +#define FORKAE_PAEF_128_256_NONCE_SIZE 14 + +/** + * \brief Size of the key for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PAEF-ForkSkinny-128-288. + */ +#define FORKAE_PAEF_128_288_NONCE_SIZE 13 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-192. + */ +#define FORKAE_SAEF_128_192_NONCE_SIZE 7 + +/** + * \brief Size of the key for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SAEF-ForkSkinny-128-256. + */ +#define FORKAE_SAEF_128_256_NONCE_SIZE 15 + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-64-192 cipher. + */ +extern aead_cipher_t const forkae_paef_64_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_paef_128_192_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_paef_128_256_cipher; + +/** + * \brief Meta-information block for the PAEF-ForkSkinny-128-288 cipher. + */ +extern aead_cipher_t const forkae_paef_128_288_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-192 cipher. + */ +extern aead_cipher_t const forkae_saef_128_192_cipher; + +/** + * \brief Meta-information block for the SAEF-ForkSkinny-128-256 cipher. + */ +extern aead_cipher_t const forkae_saef_128_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_64_192_aead_decrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-64-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_64_192_aead_encrypt() + */ +int forkae_paef_64_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_192_aead_decrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 6 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_192_aead_encrypt() + */ +int forkae_paef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_256_aead_decrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 14 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_256_aead_encrypt() + */ +int forkae_paef_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_paef_128_288_aead_decrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Decrypts and authenticates a packet with PAEF-ForkSkinny-128-288. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 13 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_paef_128_288_aead_encrypt() + */ +int forkae_paef_128_288_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_192_aead_decrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-192. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 7 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_192_aead_encrypt() + */ +int forkae_saef_128_192_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); + +/** + * \brief Encrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa forkae_saef_128_256_aead_decrypt() + */ +int forkae_saef_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with SAEF-ForkSkinny-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 15 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa forkae_saef_128_256_aead_encrypt() + */ +int forkae_saef_128_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-paef.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-paef.h new file mode 100644 index 0000000..6f57b2b --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-paef.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE PAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_paef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_COUNTER_SIZE Size of the counter value for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Limit on the amount of data we can process based on the counter size */ +#define FORKAE_PAEF_DATA_LIMIT \ + ((unsigned long long)((1ULL << (FORKAE_COUNTER_SIZE * 8)) * \ + (FORKAE_BLOCK_SIZE / 8)) - FORKAE_BLOCK_SIZE) + +/* Processes the associated data in PAEF mode */ +STATIC_INLINE void FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter) + (unsigned char tweakey[FORKAE_TWEAKEY_SIZE], + unsigned long long counter, unsigned char domain) +{ + unsigned posn; + counter |= (((unsigned long long)domain) << (FORKAE_COUNTER_SIZE * 8 - 3)); + for (posn = 0; posn < FORKAE_COUNTER_SIZE; ++posn) { + tweakey[16 + FORKAE_NONCE_SIZE + FORKAE_COUNTER_SIZE - 1 - posn] = + (unsigned char)counter; + counter >>= 8; + } +} + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned long long counter; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || mlen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + counter = 1; + while (mlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, m); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned long long counter; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Validate the size of the associated data and plaintext as there + * is a limit on the size of the PAEF counter field */ + if (adlen > FORKAE_PAEF_DATA_LIMIT || clen > FORKAE_PAEF_DATA_LIMIT) + return -2; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + + /* Tag value starts at zero. We will XOR this with all of the + * intermediate tag values that are calculated for each block */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + counter = 1; + while (adlen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 0); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + ++counter; + } + if (adlen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 1); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, ad); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, sizeof(block) - temp - 1); + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 3); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, block, block); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + counter = 1; + while (clen > FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 4); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, c); + lw_xor_block(tag, block, FORKAE_BLOCK_SIZE); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + ++counter; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 5); + lw_xor_block_2_src(m, c, tag, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, m); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, sizeof(tag)); + } else { + unsigned temp = (unsigned)clen; + unsigned char block2[FORKAE_BLOCK_SIZE]; + int check; + FORKAE_CONCAT(FORKAE_ALG_NAME,_set_counter)(tweakey, counter, 7); + lw_xor_block_2_src(block2, tag, c, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, block2, block, block2); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (block2 + temp, FORKAE_BLOCK_SIZE - temp); + memcpy(m, block2, temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE PAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT +#undef FORKAE_PAEF_DATA_LIMIT diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-saef.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-saef.h new file mode 100644 index 0000000..768bba4 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkae-saef.h @@ -0,0 +1,251 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ForkAE SAEF variant. + * + * FORKAE_ALG_NAME Name of the FORKAE algorithm; e.g. forkae_saef_128_256 + * FORKAE_BLOCK_SIZE Size of the block for the cipher (8 or 16 bytes). + * FORKAE_NONCE_SIZE Size of the nonce for the cipher in bytes. + * FORKAE_TWEAKEY_SIZE Size of the tweakey for the underlying forked cipher. + * FORKAE_REDUCED_TWEAKEY_SIZE Size of the reduced tweakey without padding. + * FORKAE_BLOCK_FUNC Name of the block function; e.g. forkskinny_128_256 + */ +#if defined(FORKAE_ALG_NAME) + +#define FORKAE_CONCAT_INNER(name,suffix) name##suffix +#define FORKAE_CONCAT(name,suffix) FORKAE_CONCAT_INNER(name,suffix) + +/* Check that the last block is padded correctly; -1 if ok, 0 if not */ +STATIC_INLINE int FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (const unsigned char *block, unsigned len) +{ + int check = block[0] ^ 0x80; + while (len > 1) { + --len; + check |= block[len]; + } + return (check - 1) >> 8; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + FORKAE_BLOCK_SIZE; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || mlen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (mlen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || mlen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then generate the tag and we are done */ + if (!mlen) { + memcpy(c, tag, sizeof(tag)); + return 0; + } + + /* Encrypt all plaintext blocks except the last */ + while (mlen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + mlen -= FORKAE_BLOCK_SIZE; + } + + /* Encrypt the last block and generate the final authentication tag */ + if (mlen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, m, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)mlen; + memcpy(block, tag, FORKAE_BLOCK_SIZE); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, c, block, block); + lw_xor_block(c, tag, FORKAE_BLOCK_SIZE); + memcpy(c + FORKAE_BLOCK_SIZE, block, temp); + } + return 0; +} + +int FORKAE_CONCAT(FORKAE_ALG_NAME,_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) +{ + unsigned char tweakey[FORKAE_TWEAKEY_SIZE]; + unsigned char tag[FORKAE_BLOCK_SIZE]; + unsigned char block[FORKAE_BLOCK_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < FORKAE_BLOCK_SIZE) + return -1; + clen -= FORKAE_BLOCK_SIZE; + *mlen = clen; + + /* Format the initial tweakey with the key and nonce */ + memcpy(tweakey, k, 16); + memcpy(tweakey + 16, npub, FORKAE_NONCE_SIZE); + memset(tweakey + 16 + FORKAE_NONCE_SIZE, 0, + FORKAE_TWEAKEY_SIZE - 16 - FORKAE_NONCE_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] = 0x08; + + /* Tag value starts at zero */ + memset(tag, 0, sizeof(tag)); + + /* Process the associated data */ + if (adlen > 0 || clen == 0) { + while (adlen > FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + ad += FORKAE_BLOCK_SIZE; + adlen -= FORKAE_BLOCK_SIZE; + } + if (clen == 0) + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x02; + if (adlen == FORKAE_BLOCK_SIZE) { + lw_xor_block(tag, ad, FORKAE_BLOCK_SIZE); + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } else if (adlen != 0 || clen == 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(tag, ad, temp); + tag[temp] ^= 0x80; + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_encrypt)(tweakey, 0, tag, tag); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + } + } + + /* If there is no message payload, then check the tag and we are done */ + if (!clen) + return aead_check_tag(m, clen, tag, c, sizeof(tag)); + + /* Decrypt all ciphertext blocks except the last */ + while (clen > FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x01; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + memcpy(tag, block, FORKAE_BLOCK_SIZE); + memset(tweakey + 16, 0, FORKAE_TWEAKEY_SIZE - 16); + c += FORKAE_BLOCK_SIZE; + m += FORKAE_BLOCK_SIZE; + clen -= FORKAE_BLOCK_SIZE; + } + + /* Decrypt the last block and check the final authentication tag */ + if (clen == FORKAE_BLOCK_SIZE) { + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x04; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt)(tweakey, m, block, block); + lw_xor_block(m, tag, FORKAE_BLOCK_SIZE); + return aead_check_tag + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, FORKAE_BLOCK_SIZE); + } else { + unsigned temp = (unsigned)clen; + unsigned char mblock[FORKAE_BLOCK_SIZE]; + int check; + lw_xor_block_2_src(block, c, tag, FORKAE_BLOCK_SIZE); + tweakey[FORKAE_TWEAKEY_REDUCED_SIZE - 1] ^= 0x05; + FORKAE_CONCAT(FORKAE_BLOCK_FUNC,_decrypt) + (tweakey, mblock, block, block); + lw_xor_block(mblock, tag, FORKAE_BLOCK_SIZE); + memcpy(m, mblock, temp); + check = FORKAE_CONCAT(FORKAE_ALG_NAME,_is_padding) + (mblock + temp, FORKAE_BLOCK_SIZE - temp); + return aead_check_tag_precheck + (mtemp, *mlen, block, c + FORKAE_BLOCK_SIZE, temp, check); + } +} + +#endif /* FORKAE_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ForkAE SAEF algorithm */ +#undef FORKAE_ALG_NAME +#undef FORKAE_BLOCK_SIZE +#undef FORKAE_NONCE_SIZE +#undef FORKAE_COUNTER_SIZE +#undef FORKAE_TWEAKEY_SIZE +#undef FORKAE_TWEAKEY_REDUCED_SIZE +#undef FORKAE_BLOCK_FUNC +#undef FORKAE_CONCAT_INNER +#undef FORKAE_CONCAT diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.c b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.c new file mode 100644 index 0000000..b050ff1 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.c @@ -0,0 +1,988 @@ +/* + * 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 "internal-forkskinny.h" +#include "internal-skinnyutil.h" + +/** + * \brief 7-bit round constants for all ForkSkinny block ciphers. + */ +static unsigned char const RC[87] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d, + 0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73, + 0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57, + 0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d, + 0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53, + 0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15, + 0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02, + 0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71, + 0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b, + 0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25, + 0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10 +}; + +/** + * \brief Number of rounds of ForkSkinny-128-256 before forking. + */ +#define FORKSKINNY_128_256_ROUNDS_BEFORE 21 + +/** + * \brief Number of rounds of ForkSkinny-128-256 after forking. + */ +#define FORKSKINNY_128_256_ROUNDS_AFTER 27 + +/** + * \brief State information for ForkSkinny-128-256. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_256_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-256. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); +} + +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_BEFORE; ++round) { + forkskinny_128_256_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-256 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_256_inv_round + (forkskinny_128_256_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_256_state_t state; + forkskinny_128_256_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_256_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_256_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_256_ROUNDS_BEFORE; + round < (FORKSKINNY_128_256_ROUNDS_BEFORE + + FORKSKINNY_128_256_ROUNDS_AFTER); ++round) { + forkskinny_128_256_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-128-384 before forking. + */ +#define FORKSKINNY_128_384_ROUNDS_BEFORE 25 + +/** + * \brief Number of rounds of ForkSkinny-128-384 after forking. + */ +#define FORKSKINNY_128_384_ROUNDS_AFTER 31 + +/** + * \brief State information for ForkSkinny-128-384. + */ +typedef struct +{ + uint32_t TK1[4]; /**< First part of the tweakey */ + uint32_t TK2[4]; /**< Second part of the tweakey */ + uint32_t TK3[4]; /**< Third part of the tweakey */ + uint32_t S[4]; /**< Current block state */ + +} forkskinny_128_384_state_t; + +/** + * \brief Applies one round of ForkSkinny-128-384. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(state->TK1); + skinny128_permute_tk(state->TK2); + skinny128_permute_tk(state->TK3); + skinny128_LFSR2(state->TK2[0]); + skinny128_LFSR2(state->TK2[1]); + skinny128_LFSR3(state->TK3[0]); + skinny128_LFSR3(state->TK3[1]); +} + +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_BEFORE; ++round) { + forkskinny_128_384_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint32_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x08040201U; /* Branching constant */ + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&state, round); + } + le_store_word32(output_right, state.S[0]); + le_store_word32(output_right + 4, state.S[1]); + le_store_word32(output_right + 8, state.S[2]); + le_store_word32(output_right + 12, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-128-384 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_128_384_inv_round + (forkskinny_128_384_state_t *state, unsigned round) +{ + uint32_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1 and TK2 for the next round */ + skinny128_inv_LFSR2(state->TK2[0]); + skinny128_inv_LFSR2(state->TK2[1]); + skinny128_inv_LFSR3(state->TK3[0]); + skinny128_inv_LFSR3(state->TK3[1]); + skinny128_inv_permute_tk(state->TK1); + skinny128_inv_permute_tk(state->TK2); + skinny128_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left, which moves the cell + * values down closer to the LSB. That is, we do a right + * rotate on the word to rotate the cells in the word left */ + s1 = rightRotate8(s1); + s2 = rightRotate16(s2); + s3 = rightRotate24(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + (rc & 0x0F) ^ 0x00020000; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_128_384_state_t state; + forkskinny_128_384_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = le_load_word32(key); + state.TK1[1] = le_load_word32(key + 4); + state.TK1[2] = le_load_word32(key + 8); + state.TK1[3] = le_load_word32(key + 12); + state.TK2[0] = le_load_word32(key + 16); + state.TK2[1] = le_load_word32(key + 20); + state.TK2[2] = le_load_word32(key + 24); + state.TK2[3] = le_load_word32(key + 28); + state.TK3[0] = le_load_word32(key + 32); + state.TK3[1] = le_load_word32(key + 36); + state.TK3[2] = le_load_word32(key + 40); + state.TK3[3] = le_load_word32(key + 44); + state.S[0] = le_load_word32(input); + state.S[1] = le_load_word32(input + 4); + state.S[2] = le_load_word32(input + 8); + state.S[3] = le_load_word32(input + 12); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); ++round) { + skinny128_permute_tk(state.TK1); + skinny128_permute_tk(state.TK2); + skinny128_permute_tk(state.TK3); + skinny128_LFSR2(state.TK2[0]); + skinny128_LFSR2(state.TK2[1]); + skinny128_LFSR3(state.TK3[0]); + skinny128_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER * 2); + round > (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x08040201U; + state.S[1] ^= 0x82412010U; + state.S[2] ^= 0x28140a05U; + state.S[3] ^= 0x8844a251U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_128_384_ROUNDS_AFTER; ++round) { + skinny128_inv_LFSR2(state.TK2[0]); + skinny128_inv_LFSR2(state.TK2[1]); + skinny128_inv_LFSR3(state.TK3[0]); + skinny128_inv_LFSR3(state.TK3[1]); + skinny128_inv_permute_tk(state.TK1); + skinny128_inv_permute_tk(state.TK2); + skinny128_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_128_384_inv_round(&state, round - 1); + } + le_store_word32(output_left, state.S[0]); + le_store_word32(output_left + 4, state.S[1]); + le_store_word32(output_left + 8, state.S[2]); + le_store_word32(output_left + 12, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_128_384_ROUNDS_BEFORE; + round < (FORKSKINNY_128_384_ROUNDS_BEFORE + + FORKSKINNY_128_384_ROUNDS_AFTER); ++round) { + forkskinny_128_384_round(&fstate, round); + } + le_store_word32(output_right, fstate.S[0]); + le_store_word32(output_right + 4, fstate.S[1]); + le_store_word32(output_right + 8, fstate.S[2]); + le_store_word32(output_right + 12, fstate.S[3]); +} + +/** + * \brief Number of rounds of ForkSkinny-64-192 before forking. + */ +#define FORKSKINNY_64_192_ROUNDS_BEFORE 17 + +/** + * \brief Number of rounds of ForkSkinny-64-192 after forking. + */ +#define FORKSKINNY_64_192_ROUNDS_AFTER 23 + +/** + * \brief State information for ForkSkinny-64-192. + */ +typedef struct +{ + uint16_t TK1[4]; /**< First part of the tweakey */ + uint16_t TK2[4]; /**< Second part of the tweakey */ + uint16_t TK3[4]; /**< Third part of the tweakey */ + uint16_t S[4]; /**< Current block state */ + +} forkskinny_64_192_state_t; + +/** + * \brief Applies one round of ForkSkinny-64-192. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + * + * Note: The cells of each row are order in big-endian nibble order + * so it is easiest to manage the rows in bit-endian byte order. + */ +static void forkskinny_64_192_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Apply the S-box to all cells in the state */ + skinny64_sbox(s0); + skinny64_sbox(s1); + skinny64_sbox(s2); + skinny64_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Shift the cells in the rows right */ + s1 = rightRotate4_16(s1); + s2 = rightRotate8_16(s2); + s3 = rightRotate12_16(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_permute_tk(state->TK1); + skinny64_permute_tk(state->TK2); + skinny64_permute_tk(state->TK3); + skinny64_LFSR2(state->TK2[0]); + skinny64_LFSR2(state->TK2[1]); + skinny64_LFSR3(state->TK3[0]); + skinny64_LFSR3(state->TK3[1]); +} + +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Run all of the rounds before the forking point */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_BEFORE; ++round) { + forkskinny_64_192_round(&state, round); + } + + /* Determine which output blocks we need */ + if (output_left && output_right) { + /* We need both outputs so save the state at the forking point */ + uint16_t F[4]; + F[0] = state.S[0]; + F[1] = state.S[1]; + F[2] = state.S[2]; + F[3] = state.S[3]; + + /* Generate the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + + /* Restore the state at the forking point */ + state.S[0] = F[0]; + state.S[1] = F[1]; + state.S[2] = F[2]; + state.S[3] = F[3]; + } + if (output_left) { + /* Generate the left output block */ + state.S[0] ^= 0x1249U; /* Branching constant */ + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + } else { + /* We only need the right output block */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&state, round); + } + be_store_word16(output_right, state.S[0]); + be_store_word16(output_right + 2, state.S[1]); + be_store_word16(output_right + 4, state.S[2]); + be_store_word16(output_right + 6, state.S[3]); + } +} + +/** + * \brief Applies one round of ForkSkinny-64-192 in reverse. + * + * \param state State to apply the round to. + * \param round Number of the round to apply. + */ +static void forkskinny_64_192_inv_round + (forkskinny_64_192_state_t *state, unsigned round) +{ + uint16_t s0, s1, s2, s3, temp; + uint8_t rc; + + /* Load the state into local variables */ + s0 = state->S[0]; + s1 = state->S[1]; + s2 = state->S[2]; + s3 = state->S[3]; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny64_inv_LFSR2(state->TK2[0]); + skinny64_inv_LFSR2(state->TK2[1]); + skinny64_inv_LFSR3(state->TK3[0]); + skinny64_inv_LFSR3(state->TK3[1]); + skinny64_inv_permute_tk(state->TK1); + skinny64_inv_permute_tk(state->TK2); + skinny64_inv_permute_tk(state->TK3); + + /* Inverse mix of the columns */ + temp = s0; + s0 = s1; + s1 = s2; + s2 = s3; + s3 = temp ^ s2; + s2 ^= s0; + s1 ^= s2; + + /* Shift the cells in the rows left */ + s1 = leftRotate4_16(s1); + s2 = leftRotate8_16(s2); + s3 = leftRotate12_16(s3); + + /* XOR the round constant and the subkey for this round */ + rc = RC[round]; + s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ + ((rc & 0x0F) << 12) ^ 0x0020; + s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ + ((rc & 0x70) << 8); + s2 ^= 0x2000; + + /* Apply the inverse of the S-box to all cells in the state */ + skinny64_inv_sbox(s0); + skinny64_inv_sbox(s1); + skinny64_inv_sbox(s2); + skinny64_inv_sbox(s3); + + /* Save the local variables back to the state */ + state->S[0] = s0; + state->S[1] = s1; + state->S[2] = s2; + state->S[3] = s3; +} + +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input) +{ + forkskinny_64_192_state_t state; + forkskinny_64_192_state_t fstate; + unsigned round; + + /* Unpack the tweakey and the input */ + state.TK1[0] = be_load_word16(key); + state.TK1[1] = be_load_word16(key + 2); + state.TK1[2] = be_load_word16(key + 4); + state.TK1[3] = be_load_word16(key + 6); + state.TK2[0] = be_load_word16(key + 8); + state.TK2[1] = be_load_word16(key + 10); + state.TK2[2] = be_load_word16(key + 12); + state.TK2[3] = be_load_word16(key + 14); + state.TK3[0] = be_load_word16(key + 16); + state.TK3[1] = be_load_word16(key + 18); + state.TK3[2] = be_load_word16(key + 20); + state.TK3[3] = be_load_word16(key + 22); + state.S[0] = be_load_word16(input); + state.S[1] = be_load_word16(input + 2); + state.S[2] = be_load_word16(input + 4); + state.S[3] = be_load_word16(input + 6); + + /* Fast-forward the tweakey to the end of the key schedule */ + for (round = 0; round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); ++round) { + skinny64_permute_tk(state.TK1); + skinny64_permute_tk(state.TK2); + skinny64_permute_tk(state.TK3); + skinny64_LFSR2(state.TK2[0]); + skinny64_LFSR2(state.TK2[1]); + skinny64_LFSR3(state.TK3[0]); + skinny64_LFSR3(state.TK3[1]); + } + + /* Perform the "after" rounds on the input to get back + * to the forking point in the cipher */ + for (round = (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER * 2); + round > (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + + /* Remove the branching constant */ + state.S[0] ^= 0x1249U; + state.S[1] ^= 0x36daU; + state.S[2] ^= 0x5b7fU; + state.S[3] ^= 0xec81U; + + /* Roll the tweakey back another "after" rounds */ + for (round = 0; round < FORKSKINNY_64_192_ROUNDS_AFTER; ++round) { + skinny64_inv_LFSR2(state.TK2[0]); + skinny64_inv_LFSR2(state.TK2[1]); + skinny64_inv_LFSR3(state.TK3[0]); + skinny64_inv_LFSR3(state.TK3[1]); + skinny64_inv_permute_tk(state.TK1); + skinny64_inv_permute_tk(state.TK2); + skinny64_inv_permute_tk(state.TK3); + } + + /* Save the state and the tweakey at the forking point */ + fstate = state; + + /* Generate the left output block after another "before" rounds */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; round > 0; --round) { + forkskinny_64_192_inv_round(&state, round - 1); + } + be_store_word16(output_left, state.S[0]); + be_store_word16(output_left + 2, state.S[1]); + be_store_word16(output_left + 4, state.S[2]); + be_store_word16(output_left + 6, state.S[3]); + + /* Generate the right output block by going forward "after" + * rounds from the forking point */ + for (round = FORKSKINNY_64_192_ROUNDS_BEFORE; + round < (FORKSKINNY_64_192_ROUNDS_BEFORE + + FORKSKINNY_64_192_ROUNDS_AFTER); ++round) { + forkskinny_64_192_round(&fstate, round); + } + be_store_word16(output_right, fstate.S[0]); + be_store_word16(output_right + 2, fstate.S[1]); + be_store_word16(output_right + 4, fstate.S[2]); + be_store_word16(output_right + 6, fstate.S[3]); +} diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.h new file mode 100644 index 0000000..0c1a707 --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-forkskinny.h @@ -0,0 +1,141 @@ +/* + * 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_FORKSKINNY_H +#define LW_INTERNAL_FORKSKINNY_H + +/** + * \file internal-forkskinny.h + * \brief ForkSkinny block cipher family. + * + * ForkSkinny is a modified version of the SKINNY block cipher that + * supports "forking": half-way through the rounds the cipher is + * forked in two different directions to produce two different outputs. + * + * References: https://www.esat.kuleuven.be/cosic/forkae/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-192 also uses this function with a padded tweakey. + */ +void forkskinny_128_256_encrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-256. + * + * \param key 256-bit tweakey for ForkSkinny-128-256. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_256_decrypt + (const unsigned char key[32], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of plaintext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 128-bit input plaintext block. + * + * ForkSkinny-128-288 also uses this function with a padded tweakey. + */ +void forkskinny_128_384_encrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-128-384. + * + * \param key 384-bit tweakey for ForkSkinny-128-384. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 128-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_128_384_decrypt + (const unsigned char key[48], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Encrypts a block of input with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left First output block, or NULL if left is not required. + * \param output_right Second output block, or NULL if right is not required. + * \param input 64-bit input block. + */ +/** + * \brief Encrypts a block of plaintext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block for the ciphertext, or NULL if + * the left output is not required. + * \param output_right Right output block for the authentication tag, + * or NULL if the right output is not required. + * \param input 64-bit input plaintext block. + */ +void forkskinny_64_192_encrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +/** + * \brief Decrypts a block of ciphertext with ForkSkinny-64-192. + * + * \param key 192-bit tweakey for ForkSkinny-64-192. + * \param output_left Left output block, which is the plaintext. + * \param output_right Right output block for the authentication tag. + * \param input 64-bit input ciphertext block. + * + * Both output blocks will be populated; neither is optional. + */ +void forkskinny_64_192_decrypt + (const unsigned char key[24], unsigned char *output_left, + unsigned char *output_right, const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-skinnyutil.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-util.h b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/forkae/Implementations/crypto_aead/saefforkskinnyb128t256n120v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/api.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/encrypt.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/encrypt.c new file mode 100644 index 0000000..1286684 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "gift-cofb.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 gift_cofb_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 gift_cofb_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.c new file mode 100644 index 0000000..ed70e07 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.c @@ -0,0 +1,407 @@ +/* + * 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 "gift-cofb.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const gift_cofb_cipher = { + "GIFT-COFB", + GIFT_COFB_KEY_SIZE, + GIFT_COFB_NONCE_SIZE, + GIFT_COFB_TAG_SIZE, + AEAD_FLAG_NONE, + gift_cofb_aead_encrypt, + gift_cofb_aead_decrypt +}; + +/** + * \brief Structure of an L value. + * + * The value is assumed to have already been converted from big-endian + * to host byte order. + */ +typedef struct +{ + uint32_t x; /**< High word of the value */ + uint32_t y; /**< Low word of the value */ + +} gift_cofb_l_t; + +/** + * \brief Structure of a 128-bit block in host byte order. + * + * The block is assumed to have already been converted from big-endian + * to host byte order. + */ +typedef union +{ + uint32_t x[4]; /**< Words of the block */ + uint8_t y[16]; /**< Bytes of the block */ + +} gift_cofb_block_t; + +/** + * \brief Doubles an L value in the F(2^64) field. + * + * \param L The value to be doubled. + * + * L = L << 1 if the top-most bit is 0, or L = (L << 1) ^ 0x1B otherwise. + */ +#define gift_cofb_double_L(L) \ + do { \ + uint32_t mask = ((int32_t)((L)->x)) >> 31; \ + (L)->x = ((L)->x << 1) | ((L)->y >> 31); \ + (L)->y = ((L)->y << 1) ^ (mask & 0x1B); \ + } while (0) + +/** + * \brief Triples an L value in the F(2^64) field. + * + * \param L The value to be tripled. + * + * L = double(L) ^ L + */ +#define gift_cofb_triple_L(L) \ + do { \ + uint32_t mask = ((int32_t)((L)->x)) >> 31; \ + uint32_t tx = ((L)->x << 1) | ((L)->y >> 31); \ + uint32_t ty = ((L)->y << 1) ^ (mask & 0x1B); \ + (L)->x ^= tx; \ + (L)->y ^= ty; \ + } while (0) + +/** + * \brief Applies the GIFT-COFB feedback function to Y. + * + * \param Y The value to be modified with the feedback function. + * + * Y is divided into L and R halves and then (R, L <<< 1) is returned. + */ +#define gift_cofb_feedback(Y) \ + do { \ + uint32_t lx = (Y)->x[0]; \ + uint32_t ly = (Y)->x[1]; \ + (Y)->x[0] = (Y)->x[2]; \ + (Y)->x[1] = (Y)->x[3]; \ + (Y)->x[2] = (lx << 1) | (ly >> 31); \ + (Y)->x[3] = (ly << 1) | (lx >> 31); \ + } while (0) + +/** + * \brief Process the associated data for GIFT-COFB encryption or decryption. + * + * \param ks The GIFT-128 key schedule to use. + * \param Y GIFT-COFB internal state. + * \param L GIFT-COFB internal state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the plaintext in bytes. + */ +static void gift_cofb_assoc_data + (gift128b_key_schedule_t *ks, gift_cofb_block_t *Y, gift_cofb_l_t *L, + const unsigned char *ad, unsigned long long adlen, unsigned long long mlen) +{ + /* Deal with all associated data blocks except the last */ + while (adlen > 16) { + gift_cofb_double_L(L); + gift_cofb_feedback(Y); + Y->x[0] ^= L->x ^ be_load_word32(ad); + Y->x[1] ^= L->y ^ be_load_word32(ad + 4); + Y->x[2] ^= be_load_word32(ad + 8); + Y->x[3] ^= be_load_word32(ad + 12); + gift128b_encrypt_preloaded(ks, Y->x, Y->x); + ad += 16; + adlen -= 16; + } + + /* Pad and deal with the last block */ + gift_cofb_feedback(Y); + if (adlen == 16) { + Y->x[0] ^= be_load_word32(ad); + Y->x[1] ^= be_load_word32(ad + 4); + Y->x[2] ^= be_load_word32(ad + 8); + Y->x[3] ^= be_load_word32(ad + 12); + gift_cofb_triple_L(L); + } else { + unsigned temp = (unsigned)adlen; + unsigned char padded[16]; + memcpy(padded, ad, temp); + padded[temp] = 0x80; + memset(padded + temp + 1, 0, 16 - temp - 1); + Y->x[0] ^= be_load_word32(padded); + Y->x[1] ^= be_load_word32(padded + 4); + Y->x[2] ^= be_load_word32(padded + 8); + Y->x[3] ^= be_load_word32(padded + 12); + gift_cofb_triple_L(L); + gift_cofb_triple_L(L); + } + if (mlen == 0) { + gift_cofb_triple_L(L); + gift_cofb_triple_L(L); + } + Y->x[0] ^= L->x; + Y->x[1] ^= L->y; + gift128b_encrypt_preloaded(ks, Y->x, Y->x); +} + +/** @cond cofb_byte_swap */ + +/* Byte-swap a block if the platform is little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define gift_cofb_byte_swap_word(y) \ + (__extension__ ({ \ + uint32_t _y = (y); \ + (_y >> 24) | (_y << 24) | ((_y << 8) & 0x00FF0000U) | \ + ((_y >> 8) & 0x0000FF00U); \ + })) +#define gift_cofb_byte_swap(x) \ + do { \ + (x)[0] = gift_cofb_byte_swap_word((x)[0]); \ + (x)[1] = gift_cofb_byte_swap_word((x)[1]); \ + (x)[2] = gift_cofb_byte_swap_word((x)[2]); \ + (x)[3] = gift_cofb_byte_swap_word((x)[3]); \ + } while (0) +#else +#define gift_cofb_byte_swap(x) do { ; } while (0) +#endif + +/** @endcond */ + +int gift_cofb_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) +{ + gift128b_key_schedule_t ks; + gift_cofb_block_t Y; + gift_cofb_l_t L; + gift_cofb_block_t P; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + GIFT_COFB_TAG_SIZE; + + /* Set up the key schedule and use it to encrypt the nonce */ + if (!gift128b_init(&ks, k, GIFT_COFB_KEY_SIZE)) + return -1; + Y.x[0] = be_load_word32(npub); + Y.x[1] = be_load_word32(npub + 4); + Y.x[2] = be_load_word32(npub + 8); + Y.x[3] = be_load_word32(npub + 12); + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + L.x = Y.x[0]; + L.y = Y.x[1]; + + /* Authenticate the associated data */ + gift_cofb_assoc_data(&ks, &Y, &L, ad, adlen, mlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + /* Deal with all plaintext blocks except the last */ + while (mlen > 16) { + P.x[0] = be_load_word32(m); + P.x[1] = be_load_word32(m + 4); + P.x[2] = be_load_word32(m + 8); + P.x[3] = be_load_word32(m + 12); + be_store_word32(c, Y.x[0] ^ P.x[0]); + be_store_word32(c + 4, Y.x[1] ^ P.x[1]); + be_store_word32(c + 8, Y.x[2] ^ P.x[2]); + be_store_word32(c + 12, Y.x[3] ^ P.x[3]); + gift_cofb_double_L(&L); + gift_cofb_feedback(&Y); + Y.x[0] ^= L.x ^ P.x[0]; + Y.x[1] ^= L.y ^ P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and deal with the last plaintext block */ + if (mlen == 16) { + P.x[0] = be_load_word32(m); + P.x[1] = be_load_word32(m + 4); + P.x[2] = be_load_word32(m + 8); + P.x[3] = be_load_word32(m + 12); + be_store_word32(c, Y.x[0] ^ P.x[0]); + be_store_word32(c + 4, Y.x[1] ^ P.x[1]); + be_store_word32(c + 8, Y.x[2] ^ P.x[2]); + be_store_word32(c + 12, Y.x[3] ^ P.x[3]); + gift_cofb_feedback(&Y); + Y.x[0] ^= P.x[0]; + Y.x[1] ^= P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift_cofb_triple_L(&L); + c += 16; + } else { + unsigned temp = (unsigned)mlen; + gift_cofb_block_t padded; + memcpy(padded.y, m, temp); + padded.y[temp] = 0x80; + memset(padded.y + temp + 1, 0, 16 - temp - 1); + P.x[0] = be_load_word32(padded.y); + P.x[1] = be_load_word32(padded.y + 4); + P.x[2] = be_load_word32(padded.y + 8); + P.x[3] = be_load_word32(padded.y + 12); + gift_cofb_byte_swap(padded.x); + padded.x[0] ^= Y.x[0]; + padded.x[1] ^= Y.x[1]; + padded.x[2] ^= Y.x[2]; + padded.x[3] ^= Y.x[3]; + gift_cofb_byte_swap(padded.x); + memcpy(c, padded.y, temp); + gift_cofb_feedback(&Y); + Y.x[0] ^= P.x[0]; + Y.x[1] ^= P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift_cofb_triple_L(&L); + gift_cofb_triple_L(&L); + c += temp; + } + Y.x[0] ^= L.x; + Y.x[1] ^= L.y; + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + } + + /* Generate the final authentication tag */ + be_store_word32(c, Y.x[0]); + be_store_word32(c + 4, Y.x[1]); + be_store_word32(c + 8, Y.x[2]); + be_store_word32(c + 12, Y.x[3]); + return 0; +} + +int gift_cofb_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) +{ + gift128b_key_schedule_t ks; + gift_cofb_block_t Y; + gift_cofb_l_t L; + gift_cofb_block_t P; + unsigned char *mtemp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < GIFT_COFB_TAG_SIZE) + return -1; + *mlen = clen - GIFT_COFB_TAG_SIZE; + + /* Set up the key schedule and use it to encrypt the nonce */ + if (!gift128b_init(&ks, k, GIFT_COFB_KEY_SIZE)) + return -1; + Y.x[0] = be_load_word32(npub); + Y.x[1] = be_load_word32(npub + 4); + Y.x[2] = be_load_word32(npub + 8); + Y.x[3] = be_load_word32(npub + 12); + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + L.x = Y.x[0]; + L.y = Y.x[1]; + + /* Authenticate the associated data */ + gift_cofb_assoc_data(&ks, &Y, &L, ad, adlen, *mlen); + + /* Decrypt the ciphertext to produce the plaintext */ + mtemp = m; + clen -= GIFT_COFB_TAG_SIZE; + if (clen > 0) { + /* Deal with all ciphertext blocks except the last */ + while (clen > 16) { + P.x[0] = Y.x[0] ^ be_load_word32(c); + P.x[1] = Y.x[1] ^ be_load_word32(c + 4); + P.x[2] = Y.x[2] ^ be_load_word32(c + 8); + P.x[3] = Y.x[3] ^ be_load_word32(c + 12); + be_store_word32(m, P.x[0]); + be_store_word32(m + 4, P.x[1]); + be_store_word32(m + 8, P.x[2]); + be_store_word32(m + 12, P.x[3]); + gift_cofb_double_L(&L); + gift_cofb_feedback(&Y); + Y.x[0] ^= L.x ^ P.x[0]; + Y.x[1] ^= L.y ^ P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + c += 16; + m += 16; + clen -= 16; + } + + /* Pad and deal with the last ciphertext block */ + if (clen == 16) { + P.x[0] = Y.x[0] ^ be_load_word32(c); + P.x[1] = Y.x[1] ^ be_load_word32(c + 4); + P.x[2] = Y.x[2] ^ be_load_word32(c + 8); + P.x[3] = Y.x[3] ^ be_load_word32(c + 12); + be_store_word32(m, P.x[0]); + be_store_word32(m + 4, P.x[1]); + be_store_word32(m + 8, P.x[2]); + be_store_word32(m + 12, P.x[3]); + gift_cofb_feedback(&Y); + Y.x[0] ^= P.x[0]; + Y.x[1] ^= P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift_cofb_triple_L(&L); + c += 16; + } else { + unsigned temp = (unsigned)clen; + P.x[0] = Y.x[0]; + P.x[1] = Y.x[1]; + P.x[2] = Y.x[2]; + P.x[3] = Y.x[3]; + gift_cofb_byte_swap(P.x); + lw_xor_block_2_dest(m, P.y, c, temp); + P.y[temp] = 0x80; + memset(P.y + temp + 1, 0, 16 - temp - 1); + gift_cofb_byte_swap(P.x); + gift_cofb_feedback(&Y); + Y.x[0] ^= P.x[0]; + Y.x[1] ^= P.x[1]; + Y.x[2] ^= P.x[2]; + Y.x[3] ^= P.x[3]; + gift_cofb_triple_L(&L); + gift_cofb_triple_L(&L); + c += temp; + } + Y.x[0] ^= L.x; + Y.x[1] ^= L.y; + gift128b_encrypt_preloaded(&ks, Y.x, Y.x); + } + + /* Check the authentication tag at the end of the packet */ + gift_cofb_byte_swap(Y.x); + return aead_check_tag(mtemp, *mlen, Y.y, c, GIFT_COFB_TAG_SIZE); +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.h new file mode 100644 index 0000000..670d042 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/gift-cofb.h @@ -0,0 +1,127 @@ +/* + * 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_GIFT_COFB_H +#define LWCRYPTO_GIFT_COFB_H + +#include "aead-common.h" + +/** + * \file gift-cofb.h + * \brief GIFT-COFB authenticated encryption algorithm. + * + * GIFT-COFB is an authenticated encryption algorithm that combines + * the COFB (COmbined FeedBack) block cipher mode with the GIFT-128 + * block cipher. The algorithm has a 128-bit key, a 128-bit nonce, + * and a 128-bit authentication tag. + * + * References: https://www.isical.ac.in/~lightweight/COFB/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for GIFT-COFB. + */ +#define GIFT_COFB_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all GIFT-COFB family members. + */ +#define GIFT_COFB_TAG_SIZE 16 + +/** + * \brief Size of the nonce for GIFT-COFB. + */ +#define GIFT_COFB_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the GIFT-COFB cipher. + */ +extern aead_cipher_t const gift_cofb_cipher; + +/** + * \brief Encrypts and authenticates a packet with GIFT-COFB. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa gift_cofb_aead_decrypt() + */ +int gift_cofb_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); + +/** + * \brief Decrypts and authenticates a packet with GIFT-COFB-0. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa gift_cofb_aead_encrypt() + */ +int gift_cofb_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-util.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.c b/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.h b/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/api.h b/gimli/Implementations/crypto_aead/gimli24v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/encrypt.c b/gimli/Implementations/crypto_aead/gimli24v1/rhys/encrypt.c new file mode 100644 index 0000000..53f563e --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "gimli24.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 gimli24_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 gimli24_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.c b/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.c new file mode 100644 index 0000000..4bc7d9f --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.c @@ -0,0 +1,330 @@ +/* + * 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 "gimli24.h" +#include "internal-gimli24.h" +#include + +aead_cipher_t const gimli24_cipher = { + "GIMLI-24", + GIMLI24_KEY_SIZE, + GIMLI24_NONCE_SIZE, + GIMLI24_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + gimli24_aead_encrypt, + gimli24_aead_decrypt +}; + +aead_hash_algorithm_t const gimli24_hash_algorithm = { + "GIMLI-24-HASH", + sizeof(gimli24_hash_state_t), + GIMLI24_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + gimli24_hash, + (aead_hash_init_t)gimli24_hash_init, + (aead_hash_update_t)gimli24_hash_absorb, + (aead_hash_finalize_t)gimli24_hash_finalize, + (aead_xof_absorb_t)gimli24_hash_absorb, + (aead_xof_squeeze_t)gimli24_hash_squeeze +}; + +/** + * \brief Number of bytes of input or output data to process per block. + */ +#define GIMLI24_BLOCK_SIZE 16 + +/** + * \brief Structure of the GIMLI-24 state as both an array of words + * and an array of bytes. + */ +typedef union +{ + uint32_t words[12]; /**< Words in the state */ + uint8_t bytes[48]; /**< Bytes in the state */ + +} gimli24_state_t; + +/** + * \brief Absorbs data into a GIMLI-24 state. + * + * \param state The state to absorb the data into. + * \param data Points to the data to be absorbed. + * \param len Length of the data to be absorbed. + */ +static void gimli24_absorb + (gimli24_state_t *state, const unsigned char *data, unsigned long long len) +{ + unsigned temp; + while (len >= GIMLI24_BLOCK_SIZE) { + lw_xor_block(state->bytes, data, GIMLI24_BLOCK_SIZE); + gimli24_permute(state->words); + data += GIMLI24_BLOCK_SIZE; + len -= GIMLI24_BLOCK_SIZE; + } + temp = (unsigned)len; + lw_xor_block(state->bytes, data, temp); + state->bytes[temp] ^= 0x01; /* Padding */ + state->bytes[47] ^= 0x01; + gimli24_permute(state->words); +} + +/** + * \brief Encrypts a block of data with a GIMLI-24 state. + * + * \param state The state to encrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to encrypt from \a src into \a dest. + */ +static void gimli24_encrypt + (gimli24_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len) +{ + unsigned temp; + while (len >= GIMLI24_BLOCK_SIZE) { + lw_xor_block_2_dest(dest, state->bytes, src, GIMLI24_BLOCK_SIZE); + gimli24_permute(state->words); + dest += GIMLI24_BLOCK_SIZE; + src += GIMLI24_BLOCK_SIZE; + len -= GIMLI24_BLOCK_SIZE; + } + temp = (unsigned)len; + lw_xor_block_2_dest(dest, state->bytes, src, temp); + state->bytes[temp] ^= 0x01; /* Padding */ + state->bytes[47] ^= 0x01; + gimli24_permute(state->words); +} + +/** + * \brief Decrypts a block of data with a GIMLI-24 state. + * + * \param state The state to decrypt with. + * \param dest Points to the destination buffer. + * \param src Points to the source buffer. + * \param len Length of the data to decrypt from \a src into \a dest. + */ +static void gimli24_decrypt + (gimli24_state_t *state, unsigned char *dest, + const unsigned char *src, unsigned long long len) +{ + unsigned temp; + while (len >= GIMLI24_BLOCK_SIZE) { + lw_xor_block_swap(dest, state->bytes, src, GIMLI24_BLOCK_SIZE); + gimli24_permute(state->words); + dest += GIMLI24_BLOCK_SIZE; + src += GIMLI24_BLOCK_SIZE; + len -= GIMLI24_BLOCK_SIZE; + } + temp = (unsigned)len; + lw_xor_block_swap(dest, state->bytes, src, temp); + state->bytes[temp] ^= 0x01; /* Padding */ + state->bytes[47] ^= 0x01; + gimli24_permute(state->words); +} + +int gimli24_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) +{ + gimli24_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + GIMLI24_TAG_SIZE; + + /* Format the initial GIMLI state from the nonce and the key */ + memcpy(state.words, npub, GIMLI24_NONCE_SIZE); + memcpy(state.words + 4, k, GIMLI24_KEY_SIZE); + + /* Permute the initial state */ + gimli24_permute(state.words); + + /* Absorb the associated data */ + gimli24_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + gimli24_encrypt(&state, c, m, mlen); + + /* Generate the authentication tag at the end of the ciphertext */ + memcpy(c + mlen, state.bytes, GIMLI24_TAG_SIZE); + return 0; +} + +int gimli24_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) +{ + gimli24_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < GIMLI24_TAG_SIZE) + return -1; + *mlen = clen - GIMLI24_TAG_SIZE; + + /* Format the initial GIMLI state from the nonce and the key */ + memcpy(state.words, npub, GIMLI24_NONCE_SIZE); + memcpy(state.words + 4, k, GIMLI24_KEY_SIZE); + + /* Permute the initial state */ + gimli24_permute(state.words); + + /* Absorb the associated data */ + gimli24_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + gimli24_decrypt(&state, m, c, *mlen); + + /* Check the authentication tag at the end of the packet */ + return aead_check_tag + (m, *mlen, state.bytes, c + *mlen, GIMLI24_TAG_SIZE); +} + +int gimli24_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + gimli24_state_t state; + + /* Initialize the hash state to all zeroes */ + memset(&state, 0, sizeof(state)); + + /* Absorb the input */ + gimli24_absorb(&state, in, inlen); + + /* Generate the output hash */ + memcpy(out, state.bytes, GIMLI24_HASH_SIZE / 2); + gimli24_permute(state.words); + memcpy(out + GIMLI24_HASH_SIZE / 2, state.bytes, GIMLI24_HASH_SIZE / 2); + return 0; +} + +void gimli24_hash_init(gimli24_hash_state_t *state) +{ + memset(state, 0, sizeof(gimli24_hash_state_t)); +} + +#define GIMLI24_XOF_RATE 16 +#define gimli24_xof_permute() \ + gimli24_permute((uint32_t *)(state->s.state)) + +void gimli24_hash_absorb + (gimli24_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + unsigned temp; + + if (state->s.mode) { + /* We were squeezing output - go back to the absorb phase */ + state->s.mode = 0; + state->s.count = 0; + gimli24_xof_permute(); + } + + /* Handle the partial left-over block from last time */ + if (state->s.count) { + temp = GIMLI24_XOF_RATE - state->s.count; + if (temp > inlen) { + temp = (unsigned)inlen; + lw_xor_block(state->s.state + state->s.count, in, temp); + state->s.count += temp; + return; + } + lw_xor_block(state->s.state + state->s.count, in, temp); + state->s.count = 0; + in += temp; + inlen -= temp; + gimli24_xof_permute(); + } + + /* Process full blocks that are aligned at state->s.count == 0 */ + while (inlen >= GIMLI24_XOF_RATE) { + lw_xor_block(state->s.state, in, GIMLI24_XOF_RATE); + in += GIMLI24_XOF_RATE; + inlen -= GIMLI24_XOF_RATE; + gimli24_xof_permute(); + } + + /* Process the left-over block at the end of the input */ + temp = (unsigned)inlen; + lw_xor_block(state->s.state, in, temp); + state->s.count = temp; +} + +void gimli24_hash_squeeze + (gimli24_hash_state_t *state, unsigned char *out, + unsigned long long outlen) +{ + unsigned temp; + + /* Pad the final input block if we were still in the absorb phase */ + if (!state->s.mode) { + state->s.state[state->s.count] ^= 0x01; + state->s.state[47] ^= 0x01; + state->s.count = 0; + state->s.mode = 1; + } + + /* Handle left-over partial blocks from last time */ + if (state->s.count) { + temp = GIMLI24_XOF_RATE - state->s.count; + if (temp > outlen) { + temp = (unsigned)outlen; + memcpy(out, state->s.state + state->s.count, temp); + state->s.count += temp; + return; + } + memcpy(out, state->s.state + state->s.count, temp); + out += temp; + outlen -= temp; + state->s.count = 0; + } + + /* Handle full blocks */ + while (outlen >= GIMLI24_XOF_RATE) { + gimli24_xof_permute(); + memcpy(out, state->s.state, GIMLI24_XOF_RATE); + out += GIMLI24_XOF_RATE; + outlen -= GIMLI24_XOF_RATE; + } + + /* Handle the left-over block */ + if (outlen > 0) { + temp = (unsigned)outlen; + gimli24_xof_permute(); + memcpy(out, state->s.state, temp); + state->s.count = temp; + } +} + +void gimli24_hash_finalize + (gimli24_hash_state_t *state, unsigned char *out) +{ + gimli24_hash_squeeze(state, out, GIMLI24_HASH_SIZE); +} diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.h b/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.h new file mode 100644 index 0000000..f72aec7 --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/gimli24.h @@ -0,0 +1,220 @@ +/* + * 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_GIMLI24_H +#define LWCRYPTO_GIMLI24_H + +#include "aead-common.h" + +/** + * \file gimli24.h + * \brief Gimli authenticated encryption algorithm. + * + * GIMLI-24-CIPHER has a 256-bit key, a 128-bit nonce, and a 128-bit tag. + * It is the spiritual successor to the widely used ChaCha20 and has a + * similar design. + * + * This library also includes an implementation of the hash algorithm + * GIMLI-24-HASH in both regular hashing and XOF modes. + * + * References: https://gimli.cr.yp.to/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for GIMLI-24. + */ +#define GIMLI24_KEY_SIZE 32 + +/** + * \brief Size of the nonce for GIMLI-24. + */ +#define GIMLI24_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for GIMLI-24. + */ +#define GIMLI24_TAG_SIZE 16 + +/** + * \brief Size of the hash output for GIMLI-24. + */ +#define GIMLI24_HASH_SIZE 32 + +/** + * \brief State information for GIMLI-24-HASH incremental modes. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} gimli24_hash_state_t; + +/** + * \brief Meta-information block for the GIMLI-24 cipher. + */ +extern aead_cipher_t const gimli24_cipher; + +/** + * \brief Meta-information block for the GIMLI-24-HASH algorithm. + * + * This meta-information block can also be used in XOF mode. + */ +extern aead_hash_algorithm_t const gimli24_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with GIMLI-24 using the + * full AEAD mode. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa gimli24_aead_decrypt() + */ +int gimli24_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); + +/** + * \brief Decrypts and authenticates a packet with GIMLI-24 using the + * full AEAD mode. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa gimli24_aead_encrypt() + */ +int gimli24_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); + +/** + * \brief Hashes a block of input data with GIMLI-24 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * GIMLI24_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 gimli24_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for a GIMLI-24-HASH hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa gimli24_hash_absorb(), gimli24_hash_squeeze(), gimli24_hash() + */ +void gimli24_hash_init(gimli24_hash_state_t *state); + +/** + * \brief Aborbs more input data into a GIMLI-24-HASH state. + * + * \param state Hash 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 gimli24_hash_init(), gimli24_hash_squeeze() + */ +void gimli24_hash_absorb + (gimli24_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Squeezes output data from an GIMLI-24-HASH state. + * + * \param state Hash 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. + * + * \sa gimli24_hash_init(), gimli24_hash_absorb() + */ +void gimli24_hash_squeeze + (gimli24_hash_state_t *state, unsigned char *out, + unsigned long long outlen); + +/** + * \brief Returns the final hash value from a GIMLI-24-HASH hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the hash value. + * + * \note This is a wrapper around gimli24_hash_squeeze() for a fixed length + * of GIMLI24_HASH_SIZE bytes. + * + * \sa gimli24_hash_init(), gimli24_hash_absorb() + */ +void gimli24_hash_finalize + (gimli24_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.c b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.c new file mode 100644 index 0000000..ab2c830 --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.c @@ -0,0 +1,138 @@ +/* + * 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 "internal-gimli24.h" + +/* Apply the SP-box to a specific column in the state array */ +#define GIMLI24_SP(s0, s4, s8) \ + do { \ + x = leftRotate24(s0); \ + y = leftRotate9(s4); \ + s4 = y ^ x ^ ((x | s8) << 1); \ + s0 = s8 ^ y ^ ((x & y) << 3); \ + s8 = x ^ (s8 << 1) ^ ((y & s8) << 2); \ + } while (0) + +void gimli24_permute(uint32_t state[12]) +{ + uint32_t s0, s1, s2, s3, s4, s5; + uint32_t s6, s7, s8, s9, s10, s11; + uint32_t x, y; + unsigned round; + + /* Load the state into local variables and convert from little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s0 = state[0]; + s1 = state[1]; + s2 = state[2]; + s3 = state[3]; + s4 = state[4]; + s5 = state[5]; + s6 = state[6]; + s7 = state[7]; + s8 = state[8]; + s9 = state[9]; + s10 = state[10]; + s11 = state[11]; +#else + s0 = le_load_word32((const unsigned char *)(&(state[0]))); + s1 = le_load_word32((const unsigned char *)(&(state[1]))); + s2 = le_load_word32((const unsigned char *)(&(state[2]))); + s3 = le_load_word32((const unsigned char *)(&(state[3]))); + s4 = le_load_word32((const unsigned char *)(&(state[4]))); + s5 = le_load_word32((const unsigned char *)(&(state[5]))); + s6 = le_load_word32((const unsigned char *)(&(state[6]))); + s7 = le_load_word32((const unsigned char *)(&(state[7]))); + s8 = le_load_word32((const unsigned char *)(&(state[8]))); + s9 = le_load_word32((const unsigned char *)(&(state[9]))); + s10 = le_load_word32((const unsigned char *)(&(state[10]))); + s11 = le_load_word32((const unsigned char *)(&(state[11]))); +#endif + + /* Unroll and perform the rounds 4 at a time */ + for (round = 24; round > 0; round -= 4) { + /* Round 0: SP-box, small swap, add round constant */ + GIMLI24_SP(s0, s4, s8); + GIMLI24_SP(s1, s5, s9); + GIMLI24_SP(s2, s6, s10); + GIMLI24_SP(s3, s7, s11); + x = s0; + y = s2; + s0 = s1 ^ 0x9e377900U ^ round; + s1 = x; + s2 = s3; + s3 = y; + + /* Round 1: SP-box only */ + GIMLI24_SP(s0, s4, s8); + GIMLI24_SP(s1, s5, s9); + GIMLI24_SP(s2, s6, s10); + GIMLI24_SP(s3, s7, s11); + + /* Round 2: SP-box, big swap */ + GIMLI24_SP(s0, s4, s8); + GIMLI24_SP(s1, s5, s9); + GIMLI24_SP(s2, s6, s10); + GIMLI24_SP(s3, s7, s11); + x = s0; + y = s1; + s0 = s2; + s1 = s3; + s2 = x; + s3 = y; + + /* Round 3: SP-box only */ + GIMLI24_SP(s0, s4, s8); + GIMLI24_SP(s1, s5, s9); + GIMLI24_SP(s2, s6, s10); + GIMLI24_SP(s3, s7, s11); + } + + /* Convert state to little-endian if the platform is not little-endian */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; + state[4] = s4; + state[5] = s5; + state[6] = s6; + state[7] = s7; + state[8] = s8; + state[9] = s9; + state[10] = s10; + state[11] = s11; +#else + le_store_word32(((unsigned char *)(&(state[0]))), s0); + le_store_word32(((unsigned char *)(&(state[1]))), s1); + le_store_word32(((unsigned char *)(&(state[2]))), s2); + le_store_word32(((unsigned char *)(&(state[3]))), s3); + le_store_word32(((unsigned char *)(&(state[4]))), s4); + le_store_word32(((unsigned char *)(&(state[5]))), s5); + le_store_word32(((unsigned char *)(&(state[6]))), s6); + le_store_word32(((unsigned char *)(&(state[7]))), s7); + le_store_word32(((unsigned char *)(&(state[8]))), s8); + le_store_word32(((unsigned char *)(&(state[9]))), s9); + le_store_word32(((unsigned char *)(&(state[10]))), s10); + le_store_word32(((unsigned char *)(&(state[11]))), s11); +#endif +} diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.h b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.h new file mode 100644 index 0000000..c81ead1 --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-gimli24.h @@ -0,0 +1,52 @@ +/* + * 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_GIMLI24_H +#define LW_INTERNAL_GIMLI24_H + +#include "internal-util.h" + +/** + * \file internal-gimli24.h + * \brief Internal implementation of the GIMLI-24 permutation. + * + * References: https://gimli.cr.yp.to/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Permutes the GIMLI-24 state. + * + * \param state The GIMLI-24 state to be permuted. + * + * The input and output \a state will be in little-endian byte order. + */ +void gimli24_permute(uint32_t state[12]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-util.h b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/gimli/Implementations/crypto_aead/gimli24v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.c b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.h b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/api.h b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/encrypt.c b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/encrypt.c new file mode 100644 index 0000000..2724d30 --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "grain128.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 grain128_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 grain128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.c b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.c new file mode 100644 index 0000000..fa41b64 --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.c @@ -0,0 +1,151 @@ +/* + * 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 "grain128.h" +#include "internal-grain128.h" +#include + +aead_cipher_t const grain128_aead_cipher = { + "Grain-128AEAD", + GRAIN128_KEY_SIZE, + GRAIN128_NONCE_SIZE, + GRAIN128_TAG_SIZE, + AEAD_FLAG_NONE, + grain128_aead_encrypt, + grain128_aead_decrypt +}; + +/** + * \brief Encodes the associated data length in DER. + * + * \param buf The buffer to encode the length into. + * \param adlen The length of the associated data in bytes, which must be + * less than 2^32 to limit the length of the DER encoding to 5 bytes. + * + * \return The length of the DER encoding that was written to \a buf. + */ +static unsigned grain128_encode_adlen + (unsigned char buf[5], unsigned long long adlen) +{ + if (adlen < 0x80U) { + buf[0] = (unsigned char)adlen; + return 1; + } else if (adlen < 0x100U) { + buf[0] = 0x81; + buf[1] = (unsigned char)adlen; + return 2; + } else if (adlen < 0x10000U) { + buf[0] = 0x82; + buf[1] = (unsigned char)(adlen >> 8); + buf[2] = (unsigned char)adlen; + return 3; + } else if (adlen < 0x1000000U) { + buf[0] = 0x83; + buf[1] = (unsigned char)(adlen >> 16); + buf[2] = (unsigned char)(adlen >> 8); + buf[3] = (unsigned char)adlen; + return 4; + } else { + buf[0] = 0x84; + buf[1] = (unsigned char)(adlen >> 24); + buf[2] = (unsigned char)(adlen >> 16); + buf[3] = (unsigned char)(adlen >> 8); + buf[4] = (unsigned char)adlen; + return 5; + } +} + +int grain128_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) +{ + grain128_state_t state; + unsigned char der[5]; + unsigned derlen; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + GRAIN128_TAG_SIZE; + + /* Limit the amount of associated data to make DER encoding easier */ + if (adlen >= 0x100000000ULL) + return -2; + + /* Initialize the Grain-128 stream cipher with the key and nonce */ + grain128_setup(&state, k, npub); + + /* Authenticate the associated data, prefixed with the DER-encoded length */ + derlen = grain128_encode_adlen(der, adlen); + grain128_authenticate(&state, der, derlen); + grain128_authenticate(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + grain128_encrypt(&state, c, m, mlen); + + /* Generate the authentication tag */ + grain128_compute_tag(&state); + memcpy(c + mlen, state.ks, GRAIN128_TAG_SIZE); + return 0; +} + +int grain128_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) +{ + grain128_state_t state; + unsigned char der[5]; + unsigned derlen; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < GRAIN128_TAG_SIZE) + return -1; + *mlen = clen - GRAIN128_TAG_SIZE; + + /* Limit the amount of associated data to make DER encoding easier */ + if (adlen >= 0x100000000ULL) + return -2; + + /* Initialize the Grain-128 stream cipher with the key and nonce */ + grain128_setup(&state, k, npub); + + /* Authenticate the associated data, prefixed with the DER-encoded length */ + derlen = grain128_encode_adlen(der, adlen); + grain128_authenticate(&state, der, derlen); + grain128_authenticate(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= GRAIN128_TAG_SIZE; + grain128_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + grain128_compute_tag(&state); + return aead_check_tag(m, clen, state.ks, c + clen, GRAIN128_TAG_SIZE); +} diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.h b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.h new file mode 100644 index 0000000..c8d6de9 --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/grain128.h @@ -0,0 +1,125 @@ +/* + * 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_GRAIN128_H +#define LWCRYPTO_GRAIN128_H + +#include "aead-common.h" + +/** + * \file grain128.h + * \brief Grain-128AEAD authenticated encryption algorithm. + * + * Grain-128AEAD is an authenticated encryption algorithm based around a + * combination of a 128-bit linear feedback shift register (LFSR) and a + * 128-bit non-linear feedback shift register (NFSR). It is a member of + * the Grain family of stream ciphers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Grain-128AEAD. + */ +#define GRAIN128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Grain-128AEAD. + */ +#define GRAIN128_TAG_SIZE 8 + +/** + * \brief Size of the nonce for Grain-128AEAD. + */ +#define GRAIN128_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Grain-128AEAD cipher. + */ +extern aead_cipher_t const grain128_aead_cipher; + +/** + * \brief Encrypts and authenticates a packet with Grain-128AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa grain128_aead_decrypt() + */ +int grain128_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); + +/** + * \brief Decrypts and authenticates a packet with Grain-128AEAD. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa grain128_aead_encrypt() + */ +int grain128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.c b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.c new file mode 100644 index 0000000..d0d71ea --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.c @@ -0,0 +1,411 @@ +/* + * 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 "internal-grain128.h" + +/* Extracts 32 bits from the Grain state that are not word-aligned */ +#define GWORD(a, b, start_bit) \ + (((a) << ((start_bit) % 32)) ^ ((b) >> (32 - ((start_bit) % 32)))) + +/** + * \brief Performs 32 rounds of Grain-128 in parallel. + * + * \param state Grain-128 state. + * \param x 32 bits of input to be incorporated into the LFSR state, or zero. + * \param x2 Another 32 bits to be incorporated into the NFSR state, or zero. + */ +static void grain128_core + (grain128_state_t *state, uint32_t x, uint32_t x2) +{ + uint32_t s0, s1, s2, s3; + + /* From the Grain-128AEAD specification, the LFSR feedback algorithm is: + * + * s'[i] = s[i + 1] + * s'[127] = s[0] ^ s[7] ^ s[38] ^ s[70] ^ s[81] ^ s[96] ^ x + * + * The bits are numbered from the most significant bit in the first + * word of the LFSR state. Calculate the feedback bits 32 at a time. + */ + s0 = state->lfsr[0]; + s1 = state->lfsr[1]; + s2 = state->lfsr[2]; + s3 = state->lfsr[3]; + x ^= s0; /* s[0] */ + x ^= GWORD(s0, s1, 7); /* s[7] */ + x ^= GWORD(s1, s2, 38); /* s[38] */ + x ^= GWORD(s2, s3, 70); /* s[70] */ + x ^= GWORD(s2, s3, 81); /* s[81] */ + x ^= s3; /* s[96] */ + + /* Rotate the LFSR state left by 32 bits and feed s0 into the NFSR */ + state->lfsr[0] = s1; + state->lfsr[1] = s2; + state->lfsr[2] = s3; + state->lfsr[3] = x; + x2 ^= s0; + + /* Perform the NFSR feedback algorithm from the specification: + * + * b'[i] = b[i + 1] + * b'[127] = s'[127] ^ b[0] ^ b[26] ^ b[56] ^ b[91] ^ b[96] + * ^ (b[3] & b[67]) ^ (b[11] & b[13]) ^ (b[17] & b[18]) + * ^ (b[27] & b[59]) ^ (b[40] & b[48]) ^ (b[61] & b[65]) + * ^ (b[68] & b[84]) ^ (b[22] & b[24] & b[25]) + * ^ (b[70] & b[78] & b[82]) + * ^ (b[88] & b[92] & b[93] & b[95]) ^ x2 + * + * Once again, we calculate 32 feedback bits in parallel. + */ + s0 = state->nfsr[0]; + s1 = state->nfsr[1]; + s2 = state->nfsr[2]; + s3 = state->nfsr[3]; + x2 ^= s0; /* b[0] */ + x2 ^= GWORD(s0, s1, 26); /* b[26] */ + x2 ^= GWORD(s1, s2, 56); /* b[56] */ + x2 ^= GWORD(s2, s3, 91); /* b[91] */ + x2 ^= s3; /* b[96] */ + x2 ^= GWORD(s0, s1, 3) & GWORD(s2, s3, 67); /* b[3] & b[67] */ + x2 ^= GWORD(s0, s1, 11) & GWORD(s0, s1, 13); /* b[11] & b[13] */ + x2 ^= GWORD(s0, s1, 17) & GWORD(s0, s1, 18); /* b[17] & b[18] */ + x2 ^= GWORD(s0, s1, 27) & GWORD(s1, s2, 59); /* b[27] & b[59] */ + x2 ^= GWORD(s1, s2, 40) & GWORD(s1, s2, 48); /* b[40] & b[48] */ + x2 ^= GWORD(s1, s2, 61) & GWORD(s2, s3, 65); /* b[61] & b[65] */ + x2 ^= GWORD(s2, s3, 68) & GWORD(s2, s3, 84); /* b[68] & b[84] */ + x2 ^= GWORD(s0, s1, 22) & GWORD(s0, s1, 24) & /* b[22] & b[24] & b[25] */ + GWORD(s0, s1, 25); + x2 ^= GWORD(s2, s3, 70) & GWORD(s2, s3, 78) & /* b[70] & b[78] & b[82] */ + GWORD(s2, s3, 82); + x2 ^= GWORD(s2, s3, 88) & GWORD(s2, s3, 92) & /* b[88] & b[92] ... */ + GWORD(s2, s3, 93) & GWORD(s2, s3, 95); /* ... & b[93] & b[95] */ + + /* Rotate the NFSR state left by 32 bits */ + state->nfsr[0] = s1; + state->nfsr[1] = s2; + state->nfsr[2] = s3; + state->nfsr[3] = x2; +} + +/** + * \brief Generates 32 bits of pre-output data. + * + * \param state Grain-128 state. + * + * \return The generated 32 bits of pre-output data. + */ +static uint32_t grain128_preoutput(const grain128_state_t *state) +{ + uint32_t s0, s1, s2, s3; + uint32_t b0, b1, b2, b3; + uint32_t x0, x4, y; + + /* From the Grain-128AEAD specification, each pre-output bit y is given by: + * + * x[0..8] = b[12], s[8], s[13], s[20], b[95], + * s[42], s[60], s[79], s[94] + * h(x) = (x[0] & x[1]) ^ (x[2] & x[3]) ^ (x[4] & x[5]) + * ^ (x[6] & x[7]) ^ (x[0] & x[4] & x[8]) + * y = h(x) ^ s[93] ^ b[2] ^ b[15] ^ b[36] ^ b[45] + * ^ b[64] ^ b[73] ^ b[89] + * + * Calculate 32 pre-output bits in parallel. + */ + s0 = state->lfsr[0]; + s1 = state->lfsr[1]; + s2 = state->lfsr[2]; + s3 = state->lfsr[3]; + b0 = state->nfsr[0]; + b1 = state->nfsr[1]; + b2 = state->nfsr[2]; + b3 = state->nfsr[3]; + x0 = GWORD(b0, b1, 12); + x4 = GWORD(b2, b3, 95); + y = (x0 & GWORD(s0, s1, 8)); /* x[0] & x[1] */ + y ^= (GWORD(s0, s1, 13) & GWORD(s0, s1, 20)); /* x[2] & x[3] */ + y ^= (x4 & GWORD(s1, s2, 42)); /* x[4] & x[5] */ + y ^= (GWORD(s1, s2, 60) & GWORD(s2, s3, 79)); /* x[6] & x[7] */ + y ^= (x0 & x4 & GWORD(s2, s3, 94)); /* x[0] & x[4] & x[8] */ + y ^= GWORD(s2, s3, 93); /* s[93] */ + y ^= GWORD(b0, b1, 2); /* b[2] */ + y ^= GWORD(b0, b1, 15); /* b[15] */ + y ^= GWORD(b1, b2, 36); /* b[36] */ + y ^= GWORD(b1, b2, 45); /* b[45] */ + y ^= b2; /* b[64] */ + y ^= GWORD(b2, b3, 73); /* b[73] */ + y ^= GWORD(b2, b3, 89); /* b[89] */ + return y; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step_simple */ +#define bit_permute_step_simple(_y, mask, shift) \ + do { \ + (_y) = (((_y) & (mask)) << (shift)) | (((_y) >> (shift)) & (mask)); \ + } while (0) + +void grain128_setup + (grain128_state_t *state, const unsigned char *key, + const unsigned char *nonce) +{ + uint32_t k[4]; + unsigned round; + + /* Internally, the Grain-128 stream cipher uses big endian bit + * order, but the Grain-128AEAD specification for NIST uses little + * endian bit order. We need to swap the bits around when we load + * the bits of the key and the nonce. + * + * Permutation generated with "http://programming.sirrida.de/calcperm.php". + * + * P = [7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 + * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24] + */ + #define SWAP_BITS(out, in) \ + do { \ + uint32_t tmp = (in); \ + bit_permute_step_simple(tmp, 0x55555555, 1); \ + bit_permute_step_simple(tmp, 0x33333333, 2); \ + bit_permute_step_simple(tmp, 0x0f0f0f0f, 4); \ + (out) = tmp; \ + } while (0) + + /* Initialize the LFSR state with the nonce and padding */ + SWAP_BITS(state->lfsr[0], be_load_word32(nonce)); + SWAP_BITS(state->lfsr[1], be_load_word32(nonce + 4)); + SWAP_BITS(state->lfsr[2], be_load_word32(nonce + 8)); + state->lfsr[3] = 0xFFFFFFFEU; /* pad with all-1s and a terminating 0 */ + + /* Initialize the NFSR state with the key */ + SWAP_BITS(k[0], be_load_word32(key)); + SWAP_BITS(k[1], be_load_word32(key + 4)); + SWAP_BITS(k[2], be_load_word32(key + 8)); + SWAP_BITS(k[3], be_load_word32(key + 12)); + state->nfsr[0] = k[0]; + state->nfsr[1] = k[1]; + state->nfsr[2] = k[2]; + state->nfsr[3] = k[3]; + + /* Perform 256 rounds of Grain-128 to mix up the initial state. + * The rounds can be performed 32 at a time: 32 * 8 = 256 */ + for (round = 0; round < 8; ++round) { + uint32_t y = grain128_preoutput(state); + grain128_core(state, y, y); + } + + /* Absorb the key into the state again and generate the initial + * state of the accumulator and the shift register */ + state->accum = ((uint64_t)(grain128_preoutput(state))) << 32; + grain128_core(state, k[0], 0); + state->accum |= grain128_preoutput(state); + grain128_core(state, k[1], 0); + state->sr = ((uint64_t)(grain128_preoutput(state))) << 32; + grain128_core(state, k[2], 0); + state->sr |= grain128_preoutput(state); + grain128_core(state, k[3], 0); + + /* No keystream data has been generated yet */ + state->posn = sizeof(state->ks); +} + +/** + * \brief Generates the next 16 byte block of keystream output data. + * + * \param state Grain-128 state. + */ +static void grain128_next_keystream(grain128_state_t *state) +{ + unsigned posn; + for (posn = 0; posn < sizeof(state->ks); posn += 4) { + /* Get the next word of pre-output and run the Grain-128 core */ + uint32_t x = grain128_preoutput(state); + grain128_core(state, 0, 0); + + /* Grain-128 uses big-endian bit order, but the NIST functions + * that are built on top of this use little-endian bit order. + * Swap the bits around so that they are ready for use later. + * + * We also need to separate the bits: even bits are used to encrypt + * and odd bits are used to authenticate. Shift them to separate + * bytes to make it easier to access the even and odd bits later. + * + * P = [7 15 6 14 5 13 4 12 3 11 2 10 1 9 0 8 + * 23 31 22 30 21 29 20 28 19 27 18 26 17 25 16 24] + */ + bit_permute_step(x, 0x11111111, 3); + bit_permute_step(x, 0x03030303, 6); + bit_permute_step(x, 0x000f000f, 12); + bit_permute_step_simple(x, 0x00ff00ff, 8); + be_store_word32(state->ks + posn, x); + } +} + +void grain128_authenticate + (grain128_state_t *state, const unsigned char *data, + unsigned long long len) +{ + unsigned char abyte; + unsigned char sbyte; + unsigned char bit; + uint64_t accum = state->accum; + uint64_t sr = state->sr; + unsigned posn = state->posn; + while (len > 0) { + /* Fetch the next byte to be authenticated */ + abyte = *data++; + --len; + + /* Request more keystream data if necessary */ + if (posn >= sizeof(state->ks)) { + grain128_next_keystream(state); + posn = 0; + } + + /* Get the next byte of keystream to add to the shift register. + * We use the odd bytes from the keystream and ignore even ones */ + sbyte = state->ks[posn + 1]; + posn += 2; + + /* XOR the shift register with the accumulator for each 1 bit + * in the byte that we are authenticating. And shift in the + * keystream byte we retrieved above */ + for (bit = 0; bit < 8; ++bit) { + accum ^= sr & (-((uint64_t)(abyte & 0x01))); + sr = (sr << 1) ^ (sbyte & 0x01); + abyte >>= 1; + sbyte >>= 1; + } + } + state->accum = accum; + state->sr = sr; + state->posn = posn; +} + +void grain128_encrypt + (grain128_state_t *state, unsigned char *c, const unsigned char *m, + unsigned long long len) +{ + unsigned char mbyte; + unsigned char sbyte; + unsigned char bit; + uint64_t accum = state->accum; + uint64_t sr = state->sr; + unsigned posn = state->posn; + while (len > 0) { + /* Fetch the next byte to be encrypted and authenticated */ + mbyte = *m++; + --len; + + /* Request more keystream data if necessary */ + if (posn >= sizeof(state->ks)) { + grain128_next_keystream(state); + posn = 0; + } + + /* Get the next two bytes of keystream data. The even byte is + * used to encrypt the input and the odd byte is shifted into + * the shift register for authentication purposes */ + *c++ = mbyte ^ state->ks[posn]; + sbyte = state->ks[posn + 1]; + posn += 2; + + /* XOR the shift register with the accumulator for each 1 bit + * in the plaintext byte that we are authenticating. And shift + * in the keystream byte we retrieved above */ + for (bit = 0; bit < 8; ++bit) { + accum ^= sr & (-((uint64_t)(mbyte & 0x01))); + sr = (sr << 1) ^ (sbyte & 0x01); + mbyte >>= 1; + sbyte >>= 1; + } + } + state->accum = accum; + state->sr = sr; + state->posn = posn; +} + +void grain128_decrypt + (grain128_state_t *state, unsigned char *m, const unsigned char *c, + unsigned long long len) +{ + unsigned char mbyte; + unsigned char sbyte; + unsigned char bit; + uint64_t accum = state->accum; + uint64_t sr = state->sr; + unsigned posn = state->posn; + while (len > 0) { + /* Fetch the next byte to be decrypted and authenticated */ + mbyte = *c++; + --len; + + /* Request more keystream data if necessary */ + if (posn >= sizeof(state->ks)) { + grain128_next_keystream(state); + posn = 0; + } + + /* Get the next two bytes of keystream data. The even byte is + * used to decrypt the input and the odd byte is shifted into + * the shift register for authentication purposes */ + mbyte ^= state->ks[posn]; + *m++ = mbyte; + sbyte = state->ks[posn + 1]; + posn += 2; + + /* XOR the shift register with the accumulator for each 1 bit + * in the plaintext byte that we are authenticating. And shift + * in the keystream byte we retrieved above */ + for (bit = 0; bit < 8; ++bit) { + accum ^= sr & (-((uint64_t)(mbyte & 0x01))); + sr = (sr << 1) ^ (sbyte & 0x01); + mbyte >>= 1; + sbyte >>= 1; + } + } + state->accum = accum; + state->sr = sr; + state->posn = posn; +} + +void grain128_compute_tag(grain128_state_t *state) +{ + uint64_t x; + + /* Authenticate a final 1 bit as padding on the stream */ + state->accum ^= state->sr; + + /* Swap the bits of the accumulator into little endian + * order and write them to the keystream buffer */ + x = state->accum; + bit_permute_step_simple(x, 0x5555555555555555ULL, 1); + bit_permute_step_simple(x, 0x3333333333333333ULL, 2); + bit_permute_step_simple(x, 0x0f0f0f0f0f0f0f0fULL, 4); + be_store_word64(state->ks, x); +} diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.h b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.h new file mode 100644 index 0000000..4c3a6e4 --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-grain128.h @@ -0,0 +1,113 @@ +/* + * 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_GRAIN128_H +#define LW_INTERNAL_GRAIN128_H + +#include "internal-util.h" + +/** + * \file internal-grain128.h + * \brief Internal implementation of the Grain-128 stream cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Representation of the state of Grain-128. + * + * Note: The specification numbers bits starting with the most significant, + * so bit 0 is in the highest bit of the first word of each field below. + */ +typedef struct +{ + uint32_t lfsr[4]; /**< 128-bit LFSR state for Grain-128 */ + uint32_t nfsr[4]; /**< 128-bit NFSR state for Grain-128 */ + uint64_t accum; /**< 64-bit accumulator for authentication */ + uint64_t sr; /**< 64-bit shift register for authentication */ + unsigned char ks[16]; /**< Keystream block for auth or encrypt mode */ + unsigned posn; /**< Current position within the keystream */ + +} grain128_state_t; + +/** + * \brief Sets up the initial Grain-128 state with the key and nonce. + * + * \param state Grain-128 state to be initialized. + * \param key Points to the 128-bit key. + * \param nonce Points to the 96-bit nonce. + */ +void grain128_setup + (grain128_state_t *state, const unsigned char *key, + const unsigned char *nonce); + +/** + * \brief Authenticates data with Grain-128. + * + * \param state Grain-128 state. + * \param data Points to the data to be authenticated. + * \param len Length of the data to be authenticated. + */ +void grain128_authenticate + (grain128_state_t *state, const unsigned char *data, + unsigned long long len); + +/** + * \brief Encrypts and authenticates data with Grain-128. + * + * \param state Grain-128 state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param len Length of the data to be encrypted. + */ +void grain128_encrypt + (grain128_state_t *state, unsigned char *c, const unsigned char *m, + unsigned long long len); + +/** + * \brief Decrypts and authenticates data with Grain-128. + * + * \param state Grain-128 state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param len Length of the data to be decrypted. + */ +void grain128_decrypt + (grain128_state_t *state, unsigned char *m, const unsigned char *c, + unsigned long long len); + +/** + * \brief Computes the final authentiation tag. + * + * \param state Grain-128 state. + * + * The final authentication tag is written to the first 8 bytes of state->ks. + */ +void grain128_compute_tag(grain128_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-util.h b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/grain-128aead/Implementations/crypto_aead/grain128aead/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.c b/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.h b/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/api.h b/hyena/Implementations/crypto_aead/hyenav1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/encrypt.c b/hyena/Implementations/crypto_aead/hyenav1/rhys/encrypt.c new file mode 100644 index 0000000..db50784 --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "hyena.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 hyena_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 hyena_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.c b/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.c new file mode 100644 index 0000000..3af79fa --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.c @@ -0,0 +1,283 @@ +/* + * 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 "hyena.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const hyena_cipher = { + "HYENA", + HYENA_KEY_SIZE, + HYENA_NONCE_SIZE, + HYENA_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + hyena_aead_encrypt, + hyena_aead_decrypt +}; + +/** + * \brief Doubles a delta value in the F(2^64) field. + * + * \param D The delta value to be doubled. + * + * D = D << 1 if the top-most bit is 0, or D = (D << 1) ^ 0x1B otherwise. + */ +static void hyena_double_delta(unsigned char D[8]) +{ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)(D[0])) >> 7); + for (index = 0; index < 7; ++index) + D[index] = (D[index] << 1) | (D[index + 1] >> 7); + D[7] = (D[7] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Process the associated data for HYENA. + * + * \param ks Key schedule for the GIFT-128 cipher. + * \param Y Internal hash state of HYENA. + * \param D Internal hash state of HYENA. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void hyena_process_ad + (const gift128n_key_schedule_t *ks, unsigned char Y[16], + unsigned char D[8], const unsigned char *ad, + unsigned long long adlen) +{ + unsigned char feedback[16]; + hyena_double_delta(D); + while (adlen > 16) { + memcpy(feedback, ad, 16); + lw_xor_block(feedback + 8, Y + 8, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + gift128n_encrypt(ks, Y, Y); + hyena_double_delta(D); + ad += 16; + adlen -= 16; + } + if (adlen == 16) { + hyena_double_delta(D); + memcpy(feedback, ad, 16); + lw_xor_block(feedback + 8, Y + 8, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + } else { + unsigned temp = (unsigned)adlen; + hyena_double_delta(D); + hyena_double_delta(D); + memcpy(feedback, ad, temp); + feedback[temp] = 0x01; + memset(feedback + temp + 1, 0, 15 - temp); + if (temp > 8) + lw_xor_block(feedback + 8, Y + 8, temp - 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + } +} + +int hyena_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) +{ + gift128n_key_schedule_t ks; + unsigned char Y[16]; + unsigned char D[8]; + unsigned char feedback[16]; + unsigned index; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + HYENA_TAG_SIZE; + + /* Set up the key schedule and use it to encrypt the nonce */ + if (!gift128n_init(&ks, k, HYENA_KEY_SIZE)) + return -1; + Y[0] = 0; + if (adlen == 0) + Y[0] |= 0x01; + if (adlen == 0 && mlen == 0) + Y[0] |= 0x02; + Y[1] = 0; + Y[2] = 0; + Y[3] = 0; + memcpy(Y + 4, npub, HYENA_NONCE_SIZE); + gift128n_encrypt(&ks, Y, Y); + memcpy(D, Y + 8, 8); + + /* Process the associated data */ + hyena_process_ad(&ks, Y, D, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > 16) { + gift128n_encrypt(&ks, Y, Y); + hyena_double_delta(D); + memcpy(feedback, m, 16); + lw_xor_block(feedback + 8, Y + 8, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block_2_src(c, m, Y, 16); + lw_xor_block(Y, feedback, 16); + c += 16; + m += 16; + mlen -= 16; + } + gift128n_encrypt(&ks, Y, Y); + if (mlen == 16) { + hyena_double_delta(D); + hyena_double_delta(D); + memcpy(feedback, m, 16); + lw_xor_block(feedback + 8, Y + 8, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block_2_src(c, m, Y, 16); + lw_xor_block(Y, feedback, 16); + c += 16; + } else { + unsigned temp = (unsigned)mlen; + hyena_double_delta(D); + hyena_double_delta(D); + hyena_double_delta(D); + memcpy(feedback, m, temp); + feedback[temp] = 0x01; + memset(feedback + temp + 1, 0, 15 - temp); + if (temp > 8) + lw_xor_block(feedback + 8, Y + 8, temp - 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block_2_src(c, m, Y, temp); + lw_xor_block(Y, feedback, 16); + c += temp; + } + } + + /* Swap the two halves of Y and generate the authentication tag */ + for (index = 0; index < 8; ++index) { + unsigned char temp1 = Y[index]; + unsigned char temp2 = Y[index + 8]; + Y[index] = temp2; + Y[index + 8] = temp1; + } + gift128n_encrypt(&ks, c, Y); + return 0; +} + +int hyena_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) +{ + gift128n_key_schedule_t ks; + unsigned char Y[16]; + unsigned char D[8]; + unsigned char feedback[16]; + unsigned char *mtemp; + unsigned index; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < HYENA_TAG_SIZE) + return -1; + *mlen = clen - HYENA_TAG_SIZE; + + /* Set up the key schedule and use it to encrypt the nonce */ + if (!gift128n_init(&ks, k, HYENA_KEY_SIZE)) + return -1; + Y[0] = 0; + if (adlen == 0) + Y[0] |= 0x01; + if (adlen == 0 && clen == HYENA_TAG_SIZE) + Y[0] |= 0x02; + Y[1] = 0; + Y[2] = 0; + Y[3] = 0; + memcpy(Y + 4, npub, HYENA_NONCE_SIZE); + gift128n_encrypt(&ks, Y, Y); + memcpy(D, Y + 8, 8); + + /* Process the associated data */ + hyena_process_ad(&ks, Y, D, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= HYENA_TAG_SIZE; + mtemp = m; + if (clen > 0) { + while (clen > 16) { + gift128n_encrypt(&ks, Y, Y); + hyena_double_delta(D); + memcpy(feedback + 8, c + 8, 8); + lw_xor_block_2_src(m, c, Y, 16); + memcpy(feedback, m, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + c += 16; + m += 16; + clen -= 16; + } + gift128n_encrypt(&ks, Y, Y); + if (clen == 16) { + hyena_double_delta(D); + hyena_double_delta(D); + memcpy(feedback + 8, c + 8, 8); + lw_xor_block_2_src(m, c, Y, 16); + memcpy(feedback, m, 8); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + c += 16; + } else { + unsigned temp = (unsigned)clen; + hyena_double_delta(D); + hyena_double_delta(D); + hyena_double_delta(D); + if (temp > 8) { + memcpy(feedback + 8, c + 8, temp - 8); + lw_xor_block_2_src(m, c, Y, temp); + memcpy(feedback, m, 8); + } else { + lw_xor_block_2_src(m, c, Y, temp); + memcpy(feedback, m, temp); + } + feedback[temp] = 0x01; + memset(feedback + temp + 1, 0, 15 - temp); + lw_xor_block(feedback + 8, D, 8); + lw_xor_block(Y, feedback, 16); + c += temp; + } + } + + /* Swap the two halves of Y and check the authentication tag */ + for (index = 0; index < 8; ++index) { + unsigned char temp1 = Y[index]; + unsigned char temp2 = Y[index + 8]; + Y[index] = temp2; + Y[index + 8] = temp1; + } + gift128n_encrypt(&ks, Y, Y); + return aead_check_tag(mtemp, *mlen, Y, c, HYENA_TAG_SIZE); +} diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.h b/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.h new file mode 100644 index 0000000..ee9bb9c --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/hyena.h @@ -0,0 +1,126 @@ +/* + * 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_HYENA_H +#define LWCRYPTO_HYENA_H + +#include "aead-common.h" + +/** + * \file hyena.h + * \brief HYENA authenticated encryption algorithm. + * + * HYENA is an authenticated encryption algorithm that is built around the + * GIFT-128 block cipher. The algorithm has a 128-bit key, a 96-bit nonce, + * and a 128-bit authentication tag. + * + * References: https://www.isical.ac.in/~lightweight/hyena/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for HYENA. + */ +#define HYENA_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for HYENA. + */ +#define HYENA_TAG_SIZE 16 + +/** + * \brief Size of the nonce for HYENA. + */ +#define HYENA_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the HYENA cipher. + */ +extern aead_cipher_t const hyena_cipher; + +/** + * \brief Encrypts and authenticates a packet with HYENA. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa hyena_aead_decrypt() + */ +int hyena_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); + +/** + * \brief Decrypts and authenticates a packet with HYENA. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa hyena_aead_encrypt() + */ +int hyena_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.c b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.h b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-util.h b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/hyena/Implementations/crypto_aead/hyenav1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.c b/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/api.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/encrypt.c b/isap/Implementations/crypto_aead/isapa128av20/rhys/encrypt.c new file mode 100644 index 0000000..18697ad --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "isap.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 isap_ascon_128a_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 isap_ascon_128a_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.c b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-isap.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-isap.h new file mode 100644 index 0000000..ba99f2a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-isap.h @@ -0,0 +1,249 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ISAP variant. + * + * ISAP_ALG_NAME Name of the ISAP algorithm; e.g. isap_keccak_128 + * ISAP_RATE Number of bytes in the rate for hashing and encryption. + * ISAP_sH Number of rounds for hashing. + * ISAP_sE Number of rounds for encryption. + * ISAP_sB Number of rounds for key bit absorption. + * ISAP_sK Number of rounds for keying. + * ISAP_STATE Type for the permuation state; e.g. ascon_state_t + * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r". + */ +#if defined(ISAP_ALG_NAME) + +#define ISAP_CONCAT_INNER(name,suffix) name##suffix +#define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix) + +/* IV string for initialising the associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A) + [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = { + 0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for authenticating associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for encrypting payload data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/** + * \brief Re-keys the ISAP permutation state. + * + * \param state The permutation state to be re-keyed. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param iv Points to the initialization vector for this re-keying operation. + * \param data Points to the data to be absorbed to perform the re-keying. + * \param data_len Length of the data to be absorbed. + * + * The output key will be left in the leading bytes of \a state. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *iv, + const unsigned char *data, unsigned data_len) +{ + unsigned bit, num_bits; + + /* Initialize the state with the key and IV */ + memcpy(state->B, k, ISAP_KEY_SIZE); + memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE); + ISAP_PERMUTE(state, ISAP_sK); + + /* Absorb all of the bits of the data buffer one by one */ + num_bits = data_len * 8 - 1; + for (bit = 0; bit < num_bits; ++bit) { + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sB); + } + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sK); +} + +/** + * \brief Encrypts (or decrypts) a message payload with ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param c Buffer to receive the output ciphertext. + * \param m Buffer to receive the input plaintext. + * \param mlen Length of the input plaintext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Set up the re-keyed encryption key and nonce in the state */ + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE); + memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE, + npub, ISAP_NONCE_SIZE); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= ISAP_RATE) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, ISAP_RATE); + c += ISAP_RATE; + m += ISAP_RATE; + mlen -= ISAP_RATE; + } + if (mlen > 0) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, (unsigned)mlen); + } +} + +/** + * \brief Authenticates the associated data and ciphertext using ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param ad Buffer containing the associated data. + * \param adlen Length of the associated data. + * \param c Buffer containing the ciphertext. + * \param clen Length of the ciphertext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *c, unsigned long long clen, + unsigned char *tag) +{ + unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE]; + unsigned temp; + + /* Absorb the associated data */ + memcpy(state->B, npub, ISAP_NONCE_SIZE); + memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A), + sizeof(state->B) - ISAP_NONCE_SIZE); + ISAP_PERMUTE(state, ISAP_sH); + while (adlen >= ISAP_RATE) { + lw_xor_block(state->B, ad, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + ad += ISAP_RATE; + adlen -= ISAP_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */ + + /* Absorb the ciphertext */ + while (clen >= ISAP_RATE) { + lw_xor_block(state->B, c, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + c += ISAP_RATE; + clen -= ISAP_RATE; + } + temp = (unsigned)clen; + lw_xor_block(state->B, c, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + + /* Re-key the state and generate the authentication tag */ + memcpy(tag, state->B, ISAP_TAG_SIZE); + memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve)); + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE); + memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve)); + ISAP_PERMUTE(state, ISAP_sH); + memcpy(tag, state->B, ISAP_TAG_SIZE); +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ISAP_TAG_SIZE; + + /* Encrypt the plaintext to produce the ciphertext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, c, m, mlen); + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (&state, k, npub, ad, adlen, c, mlen, c + mlen); + return 0; +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + unsigned char tag[ISAP_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ISAP_TAG_SIZE) + return -1; + *mlen = clen - ISAP_TAG_SIZE; + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac)(&state, k, npub, ad, adlen, c, *mlen, tag); + + /* Decrypt the ciphertext to produce the plaintext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, m, c, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE); +} + +#endif /* ISAP_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ISAP algorithm */ +#undef ISAP_ALG_NAME +#undef ISAP_RATE +#undef ISAP_sH +#undef ISAP_sE +#undef ISAP_sB +#undef ISAP_sK +#undef ISAP_STATE +#undef ISAP_PERMUTE +#undef ISAP_CONCAT_INNER +#undef ISAP_CONCAT diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.c b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-util.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.c b/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.c new file mode 100644 index 0000000..26d50a3 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.c @@ -0,0 +1,110 @@ +/* + * 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 "isap.h" +#include "internal-keccak.h" +#include "internal-ascon.h" +#include + +aead_cipher_t const isap_keccak_128a_cipher = { + "ISAP-K-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128a_aead_encrypt, + isap_keccak_128a_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128a_cipher = { + "ISAP-A-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128a_aead_encrypt, + isap_ascon_128a_aead_decrypt +}; + +aead_cipher_t const isap_keccak_128_cipher = { + "ISAP-K-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128_aead_encrypt, + isap_keccak_128_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128_cipher = { + "ISAP-A-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128_aead_encrypt, + isap_ascon_128_aead_decrypt +}; + +/* ISAP-K-128A */ +#define ISAP_ALG_NAME isap_keccak_128a +#define ISAP_RATE (144 / 8) +#define ISAP_sH 16 +#define ISAP_sE 8 +#define ISAP_sB 1 +#define ISAP_sK 8 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128A */ +#define ISAP_ALG_NAME isap_ascon_128a +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 6 +#define ISAP_sB 1 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" + +/* ISAP-K-128 */ +#define ISAP_ALG_NAME isap_keccak_128 +#define ISAP_RATE (144 / 8) +#define ISAP_sH 20 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128 */ +#define ISAP_ALG_NAME isap_ascon_128 +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" diff --git a/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.h b/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.h new file mode 100644 index 0000000..ddf8203 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128av20/rhys/isap.h @@ -0,0 +1,330 @@ +/* + * 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_ISAP_H +#define LWCRYPTO_ISAP_H + +#include "aead-common.h" + +/** + * \file isap.h + * \brief ISAP authenticated encryption algorithm. + * + * ISAP is a family of authenticated encryption algorithms that are built + * around the Keccak-p[400] or ASCON permutations. There are four algorithms + * in the family, each of which have a 128-bit key, a 128-bit nonce, and a + * 128-bit tag: + * + * \li ISAP-K-128A based around the Keccak-p[400] permutation with a + * reduced number of rounds. This is the primary member in the family. + * \li ISAP-A-128A based around the ASCON permutation with a reduced + * number of rounds. + * \li ISAP-K-128 based around the Keccak-p[400] permutation. + * \li ISAP-A-128 based around the ASCON permutation. + * + * ISAP is designed to provide some protection against adversaries + * using differential power analysis to determine the key. The + * downside is that key setup is very slow. + * + * References: https://isap.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all ISAP family members. + */ +#define ISAP_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all ISAP family members. + */ +#define ISAP_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all ISAP family members. + */ +#define ISAP_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the ISAP-K-128A cipher. + */ +extern aead_cipher_t const isap_keccak_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128A cipher. + */ +extern aead_cipher_t const isap_ascon_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-K-128 cipher. + */ +extern aead_cipher_t const isap_keccak_128_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128 cipher. + */ +extern aead_cipher_t const isap_ascon_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128a_aead_decrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128a_aead_encrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128a_aead_decrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128a_aead_encrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128_aead_decrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128_aead_encrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128_aead_decrypt() + */ +int isap_ascon_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128_aead_encrypt() + */ +int isap_ascon_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.c b/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/api.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/encrypt.c b/isap/Implementations/crypto_aead/isapa128v20/rhys/encrypt.c new file mode 100644 index 0000000..7b2bc3a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "isap.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 isap_ascon_128_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 isap_ascon_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.c b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-isap.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-isap.h new file mode 100644 index 0000000..ba99f2a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-isap.h @@ -0,0 +1,249 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ISAP variant. + * + * ISAP_ALG_NAME Name of the ISAP algorithm; e.g. isap_keccak_128 + * ISAP_RATE Number of bytes in the rate for hashing and encryption. + * ISAP_sH Number of rounds for hashing. + * ISAP_sE Number of rounds for encryption. + * ISAP_sB Number of rounds for key bit absorption. + * ISAP_sK Number of rounds for keying. + * ISAP_STATE Type for the permuation state; e.g. ascon_state_t + * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r". + */ +#if defined(ISAP_ALG_NAME) + +#define ISAP_CONCAT_INNER(name,suffix) name##suffix +#define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix) + +/* IV string for initialising the associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A) + [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = { + 0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for authenticating associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for encrypting payload data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/** + * \brief Re-keys the ISAP permutation state. + * + * \param state The permutation state to be re-keyed. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param iv Points to the initialization vector for this re-keying operation. + * \param data Points to the data to be absorbed to perform the re-keying. + * \param data_len Length of the data to be absorbed. + * + * The output key will be left in the leading bytes of \a state. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *iv, + const unsigned char *data, unsigned data_len) +{ + unsigned bit, num_bits; + + /* Initialize the state with the key and IV */ + memcpy(state->B, k, ISAP_KEY_SIZE); + memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE); + ISAP_PERMUTE(state, ISAP_sK); + + /* Absorb all of the bits of the data buffer one by one */ + num_bits = data_len * 8 - 1; + for (bit = 0; bit < num_bits; ++bit) { + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sB); + } + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sK); +} + +/** + * \brief Encrypts (or decrypts) a message payload with ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param c Buffer to receive the output ciphertext. + * \param m Buffer to receive the input plaintext. + * \param mlen Length of the input plaintext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Set up the re-keyed encryption key and nonce in the state */ + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE); + memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE, + npub, ISAP_NONCE_SIZE); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= ISAP_RATE) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, ISAP_RATE); + c += ISAP_RATE; + m += ISAP_RATE; + mlen -= ISAP_RATE; + } + if (mlen > 0) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, (unsigned)mlen); + } +} + +/** + * \brief Authenticates the associated data and ciphertext using ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param ad Buffer containing the associated data. + * \param adlen Length of the associated data. + * \param c Buffer containing the ciphertext. + * \param clen Length of the ciphertext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *c, unsigned long long clen, + unsigned char *tag) +{ + unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE]; + unsigned temp; + + /* Absorb the associated data */ + memcpy(state->B, npub, ISAP_NONCE_SIZE); + memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A), + sizeof(state->B) - ISAP_NONCE_SIZE); + ISAP_PERMUTE(state, ISAP_sH); + while (adlen >= ISAP_RATE) { + lw_xor_block(state->B, ad, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + ad += ISAP_RATE; + adlen -= ISAP_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */ + + /* Absorb the ciphertext */ + while (clen >= ISAP_RATE) { + lw_xor_block(state->B, c, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + c += ISAP_RATE; + clen -= ISAP_RATE; + } + temp = (unsigned)clen; + lw_xor_block(state->B, c, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + + /* Re-key the state and generate the authentication tag */ + memcpy(tag, state->B, ISAP_TAG_SIZE); + memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve)); + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE); + memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve)); + ISAP_PERMUTE(state, ISAP_sH); + memcpy(tag, state->B, ISAP_TAG_SIZE); +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ISAP_TAG_SIZE; + + /* Encrypt the plaintext to produce the ciphertext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, c, m, mlen); + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (&state, k, npub, ad, adlen, c, mlen, c + mlen); + return 0; +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + unsigned char tag[ISAP_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ISAP_TAG_SIZE) + return -1; + *mlen = clen - ISAP_TAG_SIZE; + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac)(&state, k, npub, ad, adlen, c, *mlen, tag); + + /* Decrypt the ciphertext to produce the plaintext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, m, c, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE); +} + +#endif /* ISAP_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ISAP algorithm */ +#undef ISAP_ALG_NAME +#undef ISAP_RATE +#undef ISAP_sH +#undef ISAP_sE +#undef ISAP_sB +#undef ISAP_sK +#undef ISAP_STATE +#undef ISAP_PERMUTE +#undef ISAP_CONCAT_INNER +#undef ISAP_CONCAT diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.c b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-util.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.c b/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.c new file mode 100644 index 0000000..26d50a3 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.c @@ -0,0 +1,110 @@ +/* + * 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 "isap.h" +#include "internal-keccak.h" +#include "internal-ascon.h" +#include + +aead_cipher_t const isap_keccak_128a_cipher = { + "ISAP-K-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128a_aead_encrypt, + isap_keccak_128a_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128a_cipher = { + "ISAP-A-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128a_aead_encrypt, + isap_ascon_128a_aead_decrypt +}; + +aead_cipher_t const isap_keccak_128_cipher = { + "ISAP-K-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128_aead_encrypt, + isap_keccak_128_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128_cipher = { + "ISAP-A-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128_aead_encrypt, + isap_ascon_128_aead_decrypt +}; + +/* ISAP-K-128A */ +#define ISAP_ALG_NAME isap_keccak_128a +#define ISAP_RATE (144 / 8) +#define ISAP_sH 16 +#define ISAP_sE 8 +#define ISAP_sB 1 +#define ISAP_sK 8 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128A */ +#define ISAP_ALG_NAME isap_ascon_128a +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 6 +#define ISAP_sB 1 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" + +/* ISAP-K-128 */ +#define ISAP_ALG_NAME isap_keccak_128 +#define ISAP_RATE (144 / 8) +#define ISAP_sH 20 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128 */ +#define ISAP_ALG_NAME isap_ascon_128 +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" diff --git a/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.h b/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.h new file mode 100644 index 0000000..ddf8203 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapa128v20/rhys/isap.h @@ -0,0 +1,330 @@ +/* + * 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_ISAP_H +#define LWCRYPTO_ISAP_H + +#include "aead-common.h" + +/** + * \file isap.h + * \brief ISAP authenticated encryption algorithm. + * + * ISAP is a family of authenticated encryption algorithms that are built + * around the Keccak-p[400] or ASCON permutations. There are four algorithms + * in the family, each of which have a 128-bit key, a 128-bit nonce, and a + * 128-bit tag: + * + * \li ISAP-K-128A based around the Keccak-p[400] permutation with a + * reduced number of rounds. This is the primary member in the family. + * \li ISAP-A-128A based around the ASCON permutation with a reduced + * number of rounds. + * \li ISAP-K-128 based around the Keccak-p[400] permutation. + * \li ISAP-A-128 based around the ASCON permutation. + * + * ISAP is designed to provide some protection against adversaries + * using differential power analysis to determine the key. The + * downside is that key setup is very slow. + * + * References: https://isap.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all ISAP family members. + */ +#define ISAP_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all ISAP family members. + */ +#define ISAP_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all ISAP family members. + */ +#define ISAP_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the ISAP-K-128A cipher. + */ +extern aead_cipher_t const isap_keccak_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128A cipher. + */ +extern aead_cipher_t const isap_ascon_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-K-128 cipher. + */ +extern aead_cipher_t const isap_keccak_128_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128 cipher. + */ +extern aead_cipher_t const isap_ascon_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128a_aead_decrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128a_aead_encrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128a_aead_decrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128a_aead_encrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128_aead_decrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128_aead_encrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128_aead_decrypt() + */ +int isap_ascon_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128_aead_encrypt() + */ +int isap_ascon_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.c b/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/api.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/encrypt.c b/isap/Implementations/crypto_aead/isapk128av20/rhys/encrypt.c new file mode 100644 index 0000000..c54de88 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "isap.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 isap_keccak_128a_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 isap_keccak_128a_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.c b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-isap.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-isap.h new file mode 100644 index 0000000..ba99f2a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-isap.h @@ -0,0 +1,249 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ISAP variant. + * + * ISAP_ALG_NAME Name of the ISAP algorithm; e.g. isap_keccak_128 + * ISAP_RATE Number of bytes in the rate for hashing and encryption. + * ISAP_sH Number of rounds for hashing. + * ISAP_sE Number of rounds for encryption. + * ISAP_sB Number of rounds for key bit absorption. + * ISAP_sK Number of rounds for keying. + * ISAP_STATE Type for the permuation state; e.g. ascon_state_t + * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r". + */ +#if defined(ISAP_ALG_NAME) + +#define ISAP_CONCAT_INNER(name,suffix) name##suffix +#define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix) + +/* IV string for initialising the associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A) + [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = { + 0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for authenticating associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for encrypting payload data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/** + * \brief Re-keys the ISAP permutation state. + * + * \param state The permutation state to be re-keyed. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param iv Points to the initialization vector for this re-keying operation. + * \param data Points to the data to be absorbed to perform the re-keying. + * \param data_len Length of the data to be absorbed. + * + * The output key will be left in the leading bytes of \a state. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *iv, + const unsigned char *data, unsigned data_len) +{ + unsigned bit, num_bits; + + /* Initialize the state with the key and IV */ + memcpy(state->B, k, ISAP_KEY_SIZE); + memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE); + ISAP_PERMUTE(state, ISAP_sK); + + /* Absorb all of the bits of the data buffer one by one */ + num_bits = data_len * 8 - 1; + for (bit = 0; bit < num_bits; ++bit) { + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sB); + } + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sK); +} + +/** + * \brief Encrypts (or decrypts) a message payload with ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param c Buffer to receive the output ciphertext. + * \param m Buffer to receive the input plaintext. + * \param mlen Length of the input plaintext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Set up the re-keyed encryption key and nonce in the state */ + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE); + memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE, + npub, ISAP_NONCE_SIZE); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= ISAP_RATE) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, ISAP_RATE); + c += ISAP_RATE; + m += ISAP_RATE; + mlen -= ISAP_RATE; + } + if (mlen > 0) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, (unsigned)mlen); + } +} + +/** + * \brief Authenticates the associated data and ciphertext using ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param ad Buffer containing the associated data. + * \param adlen Length of the associated data. + * \param c Buffer containing the ciphertext. + * \param clen Length of the ciphertext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *c, unsigned long long clen, + unsigned char *tag) +{ + unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE]; + unsigned temp; + + /* Absorb the associated data */ + memcpy(state->B, npub, ISAP_NONCE_SIZE); + memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A), + sizeof(state->B) - ISAP_NONCE_SIZE); + ISAP_PERMUTE(state, ISAP_sH); + while (adlen >= ISAP_RATE) { + lw_xor_block(state->B, ad, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + ad += ISAP_RATE; + adlen -= ISAP_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */ + + /* Absorb the ciphertext */ + while (clen >= ISAP_RATE) { + lw_xor_block(state->B, c, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + c += ISAP_RATE; + clen -= ISAP_RATE; + } + temp = (unsigned)clen; + lw_xor_block(state->B, c, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + + /* Re-key the state and generate the authentication tag */ + memcpy(tag, state->B, ISAP_TAG_SIZE); + memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve)); + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE); + memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve)); + ISAP_PERMUTE(state, ISAP_sH); + memcpy(tag, state->B, ISAP_TAG_SIZE); +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ISAP_TAG_SIZE; + + /* Encrypt the plaintext to produce the ciphertext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, c, m, mlen); + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (&state, k, npub, ad, adlen, c, mlen, c + mlen); + return 0; +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + unsigned char tag[ISAP_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ISAP_TAG_SIZE) + return -1; + *mlen = clen - ISAP_TAG_SIZE; + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac)(&state, k, npub, ad, adlen, c, *mlen, tag); + + /* Decrypt the ciphertext to produce the plaintext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, m, c, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE); +} + +#endif /* ISAP_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ISAP algorithm */ +#undef ISAP_ALG_NAME +#undef ISAP_RATE +#undef ISAP_sH +#undef ISAP_sE +#undef ISAP_sB +#undef ISAP_sK +#undef ISAP_STATE +#undef ISAP_PERMUTE +#undef ISAP_CONCAT_INNER +#undef ISAP_CONCAT diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.c b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-util.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.c b/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.c new file mode 100644 index 0000000..26d50a3 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.c @@ -0,0 +1,110 @@ +/* + * 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 "isap.h" +#include "internal-keccak.h" +#include "internal-ascon.h" +#include + +aead_cipher_t const isap_keccak_128a_cipher = { + "ISAP-K-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128a_aead_encrypt, + isap_keccak_128a_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128a_cipher = { + "ISAP-A-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128a_aead_encrypt, + isap_ascon_128a_aead_decrypt +}; + +aead_cipher_t const isap_keccak_128_cipher = { + "ISAP-K-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128_aead_encrypt, + isap_keccak_128_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128_cipher = { + "ISAP-A-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128_aead_encrypt, + isap_ascon_128_aead_decrypt +}; + +/* ISAP-K-128A */ +#define ISAP_ALG_NAME isap_keccak_128a +#define ISAP_RATE (144 / 8) +#define ISAP_sH 16 +#define ISAP_sE 8 +#define ISAP_sB 1 +#define ISAP_sK 8 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128A */ +#define ISAP_ALG_NAME isap_ascon_128a +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 6 +#define ISAP_sB 1 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" + +/* ISAP-K-128 */ +#define ISAP_ALG_NAME isap_keccak_128 +#define ISAP_RATE (144 / 8) +#define ISAP_sH 20 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128 */ +#define ISAP_ALG_NAME isap_ascon_128 +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" diff --git a/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.h b/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.h new file mode 100644 index 0000000..ddf8203 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128av20/rhys/isap.h @@ -0,0 +1,330 @@ +/* + * 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_ISAP_H +#define LWCRYPTO_ISAP_H + +#include "aead-common.h" + +/** + * \file isap.h + * \brief ISAP authenticated encryption algorithm. + * + * ISAP is a family of authenticated encryption algorithms that are built + * around the Keccak-p[400] or ASCON permutations. There are four algorithms + * in the family, each of which have a 128-bit key, a 128-bit nonce, and a + * 128-bit tag: + * + * \li ISAP-K-128A based around the Keccak-p[400] permutation with a + * reduced number of rounds. This is the primary member in the family. + * \li ISAP-A-128A based around the ASCON permutation with a reduced + * number of rounds. + * \li ISAP-K-128 based around the Keccak-p[400] permutation. + * \li ISAP-A-128 based around the ASCON permutation. + * + * ISAP is designed to provide some protection against adversaries + * using differential power analysis to determine the key. The + * downside is that key setup is very slow. + * + * References: https://isap.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all ISAP family members. + */ +#define ISAP_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all ISAP family members. + */ +#define ISAP_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all ISAP family members. + */ +#define ISAP_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the ISAP-K-128A cipher. + */ +extern aead_cipher_t const isap_keccak_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128A cipher. + */ +extern aead_cipher_t const isap_ascon_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-K-128 cipher. + */ +extern aead_cipher_t const isap_keccak_128_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128 cipher. + */ +extern aead_cipher_t const isap_ascon_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128a_aead_decrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128a_aead_encrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128a_aead_decrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128a_aead_encrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128_aead_decrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128_aead_encrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128_aead_decrypt() + */ +int isap_ascon_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128_aead_encrypt() + */ +int isap_ascon_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.c b/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/api.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/encrypt.c b/isap/Implementations/crypto_aead/isapk128v20/rhys/encrypt.c new file mode 100644 index 0000000..72d2d68 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "isap.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 isap_keccak_128_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 isap_keccak_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.c b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.c new file mode 100644 index 0000000..12a8ec6 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.c @@ -0,0 +1,76 @@ +/* + * 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 "internal-ascon.h" + +void ascon_permute(ascon_state_t *state, uint8_t first_round) +{ + uint64_t t0, t1, t2, t3, t4; +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = be_load_word64(state->B); + uint64_t x1 = be_load_word64(state->B + 8); + uint64_t x2 = be_load_word64(state->B + 16); + uint64_t x3 = be_load_word64(state->B + 24); + uint64_t x4 = be_load_word64(state->B + 32); +#else + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; +#endif + while (first_round < 12) { + /* Add the round constant to the state */ + x2 ^= ((0x0F - first_round) << 4) | first_round; + + /* Substitution layer - apply the s-box using bit-slicing + * according to the algorithm recommended in the specification */ + x0 ^= x4; x4 ^= x3; x2 ^= x1; + t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; + t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; + x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; + x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; + + /* Linear diffusion layer */ + x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); + x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); + x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); + x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); + x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); + + /* Move onto the next round */ + ++first_round; + } +#if defined(LW_UTIL_LITTLE_ENDIAN) + be_store_word64(state->B, x0); + be_store_word64(state->B + 8, x1); + be_store_word64(state->B + 16, x2); + be_store_word64(state->B + 24, x3); + be_store_word64(state->B + 32, x4); +#else + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; +#endif +} diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.h new file mode 100644 index 0000000..d3fa3ca --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-ascon.h @@ -0,0 +1,64 @@ +/* + * 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_ASCON_H +#define LW_INTERNAL_ASCON_H + +#include "internal-util.h" + +/** + * \file internal-ascon.h + * \brief Internal implementation of the ASCON permutation. + * + * References: http://competitions.cr.yp.to/round3/asconv12.pdf, + * http://ascon.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Structure of the internal state of the ASCON permutation. + */ +typedef union +{ + uint64_t S[5]; /**< Words of the state */ + uint8_t B[40]; /**< Bytes of the state */ + +} ascon_state_t; + +/** + * \brief Permutes the ASCON state. + * + * \param state The ASCON state to be permuted. + * \param first_round The first round (of 12) to be performed; 0, 4, or 6. + * + * The input and output \a state will be in big-endian byte order. + */ +void ascon_permute(ascon_state_t *state, uint8_t first_round); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-isap.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-isap.h new file mode 100644 index 0000000..ba99f2a --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-isap.h @@ -0,0 +1,249 @@ +/* + * 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. + */ + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying ISAP variant. + * + * ISAP_ALG_NAME Name of the ISAP algorithm; e.g. isap_keccak_128 + * ISAP_RATE Number of bytes in the rate for hashing and encryption. + * ISAP_sH Number of rounds for hashing. + * ISAP_sE Number of rounds for encryption. + * ISAP_sB Number of rounds for key bit absorption. + * ISAP_sK Number of rounds for keying. + * ISAP_STATE Type for the permuation state; e.g. ascon_state_t + * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r". + */ +#if defined(ISAP_ALG_NAME) + +#define ISAP_CONCAT_INNER(name,suffix) name##suffix +#define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix) + +/* IV string for initialising the associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A) + [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = { + 0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for authenticating associated data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/* IV string for encrypting payload data */ +static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE) + [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = { + 0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1, + ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK +}; + +/** + * \brief Re-keys the ISAP permutation state. + * + * \param state The permutation state to be re-keyed. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param iv Points to the initialization vector for this re-keying operation. + * \param data Points to the data to be absorbed to perform the re-keying. + * \param data_len Length of the data to be absorbed. + * + * The output key will be left in the leading bytes of \a state. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *iv, + const unsigned char *data, unsigned data_len) +{ + unsigned bit, num_bits; + + /* Initialize the state with the key and IV */ + memcpy(state->B, k, ISAP_KEY_SIZE); + memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE); + ISAP_PERMUTE(state, ISAP_sK); + + /* Absorb all of the bits of the data buffer one by one */ + num_bits = data_len * 8 - 1; + for (bit = 0; bit < num_bits; ++bit) { + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sB); + } + state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80; + ISAP_PERMUTE(state, ISAP_sK); +} + +/** + * \brief Encrypts (or decrypts) a message payload with ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param c Buffer to receive the output ciphertext. + * \param m Buffer to receive the input plaintext. + * \param mlen Length of the input plaintext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Set up the re-keyed encryption key and nonce in the state */ + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE); + memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE, + npub, ISAP_NONCE_SIZE); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= ISAP_RATE) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, ISAP_RATE); + c += ISAP_RATE; + m += ISAP_RATE; + mlen -= ISAP_RATE; + } + if (mlen > 0) { + ISAP_PERMUTE(state, ISAP_sE); + lw_xor_block_2_src(c, state->B, m, (unsigned)mlen); + } +} + +/** + * \brief Authenticates the associated data and ciphertext using ISAP. + * + * \param state ISAP permutation state. + * \param k Points to the 128-bit key for the ISAP cipher. + * \param npub Points to the 128-bit nonce for the ISAP cipher. + * \param ad Buffer containing the associated data. + * \param adlen Length of the associated data. + * \param c Buffer containing the ciphertext. + * \param clen Length of the ciphertext. + */ +static void ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *c, unsigned long long clen, + unsigned char *tag) +{ + unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE]; + unsigned temp; + + /* Absorb the associated data */ + memcpy(state->B, npub, ISAP_NONCE_SIZE); + memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A), + sizeof(state->B) - ISAP_NONCE_SIZE); + ISAP_PERMUTE(state, ISAP_sH); + while (adlen >= ISAP_RATE) { + lw_xor_block(state->B, ad, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + ad += ISAP_RATE; + adlen -= ISAP_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */ + + /* Absorb the ciphertext */ + while (clen >= ISAP_RATE) { + lw_xor_block(state->B, c, ISAP_RATE); + ISAP_PERMUTE(state, ISAP_sH); + c += ISAP_RATE; + clen -= ISAP_RATE; + } + temp = (unsigned)clen; + lw_xor_block(state->B, c, temp); + state->B[temp] ^= 0x80; /* padding */ + ISAP_PERMUTE(state, ISAP_sH); + + /* Re-key the state and generate the authentication tag */ + memcpy(tag, state->B, ISAP_TAG_SIZE); + memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve)); + ISAP_CONCAT(ISAP_ALG_NAME,_rekey) + (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE); + memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve)); + ISAP_PERMUTE(state, ISAP_sH); + memcpy(tag, state->B, ISAP_TAG_SIZE); +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ISAP_TAG_SIZE; + + /* Encrypt the plaintext to produce the ciphertext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, c, m, mlen); + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac) + (&state, k, npub, ad, adlen, c, mlen, c + mlen); + return 0; +} + +int ISAP_CONCAT(ISAP_ALG_NAME,_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) +{ + ISAP_STATE state; + unsigned char tag[ISAP_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ISAP_TAG_SIZE) + return -1; + *mlen = clen - ISAP_TAG_SIZE; + + /* Authenticate the associated data and ciphertext to generate the tag */ + ISAP_CONCAT(ISAP_ALG_NAME,_mac)(&state, k, npub, ad, adlen, c, *mlen, tag); + + /* Decrypt the ciphertext to produce the plaintext */ + ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, m, c, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE); +} + +#endif /* ISAP_ALG_NAME */ + +/* Now undefine everything so that we can include this file again for + * another variant on the ISAP algorithm */ +#undef ISAP_ALG_NAME +#undef ISAP_RATE +#undef ISAP_sH +#undef ISAP_sE +#undef ISAP_sB +#undef ISAP_sK +#undef ISAP_STATE +#undef ISAP_PERMUTE +#undef ISAP_CONCAT_INNER +#undef ISAP_CONCAT diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.c b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.c new file mode 100644 index 0000000..c3c4011 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.c @@ -0,0 +1,204 @@ +/* + * 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 "internal-keccak.h" + +/* Faster method to compute ((x + y) % 5) that avoids the division */ +static unsigned char const addMod5Table[9] = { + 0, 1, 2, 3, 4, 0, 1, 2, 3 +}; +#define addMod5(x, y) (addMod5Table[(x) + (y)]) + +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds) +{ + static uint8_t const RC[18] = { + 0x01, 0x82, 0x8A, 0x00, 0x8B, 0x01, 0x81, 0x09, + 0x8A, 0x88, 0x09, 0x0A, 0x8B, 0x8B, 0x89, 0x03, + 0x02, 0x80 + }; + uint8_t B[5][5]; + uint8_t D; + unsigned round; + unsigned index, index2; + for (round = 18 - rounds; round < 18; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_8(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate4_8(state->A[0][3]); + B[2][0] = leftRotate1_8(state->A[0][1]); + B[3][0] = leftRotate3_8(state->A[0][4]); + B[4][0] = leftRotate6_8(state->A[0][2]); + B[0][1] = leftRotate4_8(state->A[1][1]); + B[1][1] = leftRotate4_8(state->A[1][4]); + B[2][1] = leftRotate6_8(state->A[1][2]); + B[3][1] = leftRotate4_8(state->A[1][0]); + B[4][1] = leftRotate7_8(state->A[1][3]); + B[0][2] = leftRotate3_8(state->A[2][2]); + B[1][2] = leftRotate3_8(state->A[2][0]); + B[2][2] = leftRotate1_8(state->A[2][3]); + B[3][2] = leftRotate2_8(state->A[2][1]); + B[4][2] = leftRotate7_8(state->A[2][4]); + B[0][3] = leftRotate5_8(state->A[3][3]); + B[1][3] = leftRotate5_8(state->A[3][1]); + B[2][3] = state->A[3][4]; + B[3][3] = leftRotate7_8(state->A[3][2]); + B[4][3] = leftRotate1_8(state->A[3][0]); + B[0][4] = leftRotate6_8(state->A[4][4]); + B[1][4] = leftRotate5_8(state->A[4][2]); + B[2][4] = leftRotate2_8(state->A[4][0]); + B[3][4] = state->A[4][3]; + B[4][4] = leftRotate2_8(state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define keccakp_400_permute_host keccakp_400_permute +#endif + +/* Keccak-p[400] that assumes that the input is already in host byte order */ +void keccakp_400_permute_host(keccakp_400_state_t *state, unsigned rounds) +{ + static uint16_t const RC[20] = { + 0x0001, 0x8082, 0x808A, 0x8000, 0x808B, 0x0001, 0x8081, 0x8009, + 0x008A, 0x0088, 0x8009, 0x000A, 0x808B, 0x008B, 0x8089, 0x8003, + 0x8002, 0x0080, 0x800A, 0x000A + }; + uint16_t B[5][5]; + uint16_t D; + unsigned round; + unsigned index, index2; + for (round = 20 - rounds; round < 20; ++round) { + /* Step mapping theta. The specification mentions two temporary + * arrays of size 5 called C and D. To save a bit of memory, + * we use the first row of B to store C and compute D on the fly */ + for (index = 0; index < 5; ++index) { + B[0][index] = state->A[0][index] ^ state->A[1][index] ^ + state->A[2][index] ^ state->A[3][index] ^ + state->A[4][index]; + } + for (index = 0; index < 5; ++index) { + D = B[0][addMod5(index, 4)] ^ + leftRotate1_16(B[0][addMod5(index, 1)]); + for (index2 = 0; index2 < 5; ++index2) + state->A[index2][index] ^= D; + } + + /* Step mapping rho and pi combined into a single step. + * Rotate all lanes by a specific offset and rearrange */ + B[0][0] = state->A[0][0]; + B[1][0] = leftRotate12_16(state->A[0][3]); + B[2][0] = leftRotate1_16 (state->A[0][1]); + B[3][0] = leftRotate11_16(state->A[0][4]); + B[4][0] = leftRotate14_16(state->A[0][2]); + B[0][1] = leftRotate12_16(state->A[1][1]); + B[1][1] = leftRotate4_16 (state->A[1][4]); + B[2][1] = leftRotate6_16 (state->A[1][2]); + B[3][1] = leftRotate4_16 (state->A[1][0]); + B[4][1] = leftRotate7_16 (state->A[1][3]); + B[0][2] = leftRotate11_16(state->A[2][2]); + B[1][2] = leftRotate3_16 (state->A[2][0]); + B[2][2] = leftRotate9_16 (state->A[2][3]); + B[3][2] = leftRotate10_16(state->A[2][1]); + B[4][2] = leftRotate7_16 (state->A[2][4]); + B[0][3] = leftRotate5_16 (state->A[3][3]); + B[1][3] = leftRotate13_16(state->A[3][1]); + B[2][3] = leftRotate8_16 (state->A[3][4]); + B[3][3] = leftRotate15_16(state->A[3][2]); + B[4][3] = leftRotate9_16 (state->A[3][0]); + B[0][4] = leftRotate14_16(state->A[4][4]); + B[1][4] = leftRotate13_16(state->A[4][2]); + B[2][4] = leftRotate2_16 (state->A[4][0]); + B[3][4] = leftRotate8_16 (state->A[4][3]); + B[4][4] = leftRotate2_16 (state->A[4][1]); + + /* Step mapping chi. Combine each lane with two others in its row */ + for (index = 0; index < 5; ++index) { + for (index2 = 0; index2 < 5; ++index2) { + state->A[index2][index] = + B[index2][index] ^ + ((~B[index2][addMod5(index, 1)]) & + B[index2][addMod5(index, 2)]); + } + } + + /* Step mapping iota. XOR A[0][0] with the round constant */ + state->A[0][0] ^= RC[round]; + } +} + +#if !defined(LW_UTIL_LITTLE_ENDIAN) + +/** + * \brief Reverses the bytes in a Keccak-p[400] state. + * + * \param state The Keccak-p[400] state to apply byte-reversal to. + */ +static void keccakp_400_reverse_bytes(keccakp_400_state_t *state) +{ + unsigned index; + unsigned char temp1; + unsigned char temp2; + for (index = 0; index < 50; index += 2) { + temp1 = state->B[index]; + temp2 = state->B[index + 1]; + state->B[index] = temp2; + state->B[index + 1] = temp1; + } +} + +/* Keccak-p[400] that requires byte reversal on input and output */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds) +{ + keccakp_400_reverse_bytes(state); + keccakp_400_permute_host(state, rounds); + keccakp_400_reverse_bytes(state); +} + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.h new file mode 100644 index 0000000..026da50 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-keccak.h @@ -0,0 +1,88 @@ +/* + * 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_KECCAK_H +#define LW_INTERNAL_KECCAK_H + +#include "internal-util.h" + +/** + * \file internal-keccak.h + * \brief Internal implementation of the Keccak-p permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for the Keccak-p[200] permutation. + */ +#define KECCAKP_200_STATE_SIZE 25 + +/** + * \brief Size of the state for the Keccak-p[400] permutation. + */ +#define KECCAKP_400_STATE_SIZE 50 + +/** + * \brief Structure of the internal state of the Keccak-p[200] permutation. + */ +typedef union +{ + uint8_t A[5][5]; /**< Keccak-p[200] state as a 5x5 array of lanes */ + uint8_t B[25]; /**< Keccak-p[200] state as a byte array */ + +} keccakp_200_state_t; + +/** + * \brief Structure of the internal state of the Keccak-p[400] permutation. + */ +typedef union +{ + uint16_t A[5][5]; /**< Keccak-p[400] state as a 5x5 array of lanes */ + uint8_t B[50]; /**< Keccak-p[400] state as a byte array */ + +} keccakp_400_state_t; + +/** + * \brief Permutes the Keccak-p[200] state. + * + * \param state The Keccak-p[200] state to be permuted. + * \param rounds The number of rounds to perform (up to 18). + */ +void keccakp_200_permute(keccakp_200_state_t *state, unsigned rounds); + +/** + * \brief Permutes the Keccak-p[400] state, which is assumed to be in + * little-endian byte order. + * + * \param state The Keccak-p[400] state to be permuted. + * \param rounds The number of rounds to perform (up to 20). + */ +void keccakp_400_permute(keccakp_400_state_t *state, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-util.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.c b/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.c new file mode 100644 index 0000000..26d50a3 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.c @@ -0,0 +1,110 @@ +/* + * 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 "isap.h" +#include "internal-keccak.h" +#include "internal-ascon.h" +#include + +aead_cipher_t const isap_keccak_128a_cipher = { + "ISAP-K-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128a_aead_encrypt, + isap_keccak_128a_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128a_cipher = { + "ISAP-A-128A", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128a_aead_encrypt, + isap_ascon_128a_aead_decrypt +}; + +aead_cipher_t const isap_keccak_128_cipher = { + "ISAP-K-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_keccak_128_aead_encrypt, + isap_keccak_128_aead_decrypt +}; + +aead_cipher_t const isap_ascon_128_cipher = { + "ISAP-A-128", + ISAP_KEY_SIZE, + ISAP_NONCE_SIZE, + ISAP_TAG_SIZE, + AEAD_FLAG_NONE, + isap_ascon_128_aead_encrypt, + isap_ascon_128_aead_decrypt +}; + +/* ISAP-K-128A */ +#define ISAP_ALG_NAME isap_keccak_128a +#define ISAP_RATE (144 / 8) +#define ISAP_sH 16 +#define ISAP_sE 8 +#define ISAP_sB 1 +#define ISAP_sK 8 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128A */ +#define ISAP_ALG_NAME isap_ascon_128a +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 6 +#define ISAP_sB 1 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" + +/* ISAP-K-128 */ +#define ISAP_ALG_NAME isap_keccak_128 +#define ISAP_RATE (144 / 8) +#define ISAP_sH 20 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE keccakp_400_state_t +#define ISAP_PERMUTE(s,r) keccakp_400_permute((s), (r)) +#include "internal-isap.h" + +/* ISAP-A-128 */ +#define ISAP_ALG_NAME isap_ascon_128 +#define ISAP_RATE (64 / 8) +#define ISAP_sH 12 +#define ISAP_sE 12 +#define ISAP_sB 12 +#define ISAP_sK 12 +#define ISAP_STATE ascon_state_t +#define ISAP_PERMUTE(s,r) ascon_permute((s), 12 - (r)) +#include "internal-isap.h" diff --git a/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.h b/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.h new file mode 100644 index 0000000..ddf8203 --- /dev/null +++ b/isap/Implementations/crypto_aead/isapk128v20/rhys/isap.h @@ -0,0 +1,330 @@ +/* + * 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_ISAP_H +#define LWCRYPTO_ISAP_H + +#include "aead-common.h" + +/** + * \file isap.h + * \brief ISAP authenticated encryption algorithm. + * + * ISAP is a family of authenticated encryption algorithms that are built + * around the Keccak-p[400] or ASCON permutations. There are four algorithms + * in the family, each of which have a 128-bit key, a 128-bit nonce, and a + * 128-bit tag: + * + * \li ISAP-K-128A based around the Keccak-p[400] permutation with a + * reduced number of rounds. This is the primary member in the family. + * \li ISAP-A-128A based around the ASCON permutation with a reduced + * number of rounds. + * \li ISAP-K-128 based around the Keccak-p[400] permutation. + * \li ISAP-A-128 based around the ASCON permutation. + * + * ISAP is designed to provide some protection against adversaries + * using differential power analysis to determine the key. The + * downside is that key setup is very slow. + * + * References: https://isap.iaik.tugraz.at/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all ISAP family members. + */ +#define ISAP_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all ISAP family members. + */ +#define ISAP_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all ISAP family members. + */ +#define ISAP_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the ISAP-K-128A cipher. + */ +extern aead_cipher_t const isap_keccak_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128A cipher. + */ +extern aead_cipher_t const isap_ascon_128a_cipher; + +/** + * \brief Meta-information block for the ISAP-K-128 cipher. + */ +extern aead_cipher_t const isap_keccak_128_cipher; + +/** + * \brief Meta-information block for the ISAP-A-128 cipher. + */ +extern aead_cipher_t const isap_ascon_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128a_aead_decrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128a_aead_encrypt() + */ +int isap_keccak_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128A. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128a_aead_decrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128A. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128a_aead_encrypt() + */ +int isap_ascon_128a_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-K-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_keccak_128_aead_decrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-K-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_keccak_128_aead_encrypt() + */ +int isap_keccak_128_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); + +/** + * \brief Encrypts and authenticates a packet with ISAP-A-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa isap_ascon_128_aead_decrypt() + */ +int isap_ascon_128_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); + +/** + * \brief Decrypts and authenticates a packet with ISAP-A-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa isap_ascon_128_aead_encrypt() + */ +int isap_ascon_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.c b/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.h b/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/api.h b/knot/Implementations/crypto_aead/knot128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/encrypt.c b/knot/Implementations/crypto_aead/knot128v1/rhys/encrypt.c new file mode 100644 index 0000000..0d644de --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "knot.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 knot_aead_128_256_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 knot_aead_128_256_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.c b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.c new file mode 100644 index 0000000..3486e6e --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.c @@ -0,0 +1,297 @@ +/* + * 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 "internal-knot.h" + +/* Round constants for the KNOT-256, KNOT-384, and KNOT-512 permutations */ +static uint8_t const rc6[52] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x21, 0x03, 0x06, 0x0c, 0x18, 0x31, 0x22, + 0x05, 0x0a, 0x14, 0x29, 0x13, 0x27, 0x0f, 0x1e, 0x3d, 0x3a, 0x34, 0x28, + 0x11, 0x23, 0x07, 0x0e, 0x1c, 0x39, 0x32, 0x24, 0x09, 0x12, 0x25, 0x0b, + 0x16, 0x2d, 0x1b, 0x37, 0x2e, 0x1d, 0x3b, 0x36, 0x2c, 0x19, 0x33, 0x26, + 0x0d, 0x1a, 0x35, 0x2a +}; +static uint8_t const rc7[104] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x41, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x61, 0x42, 0x05, 0x0a, 0x14, 0x28, 0x51, 0x23, 0x47, 0x0f, 0x1e, 0x3c, + 0x79, 0x72, 0x64, 0x48, 0x11, 0x22, 0x45, 0x0b, 0x16, 0x2c, 0x59, 0x33, + 0x67, 0x4e, 0x1d, 0x3a, 0x75, 0x6a, 0x54, 0x29, 0x53, 0x27, 0x4f, 0x1f, + 0x3e, 0x7d, 0x7a, 0x74, 0x68, 0x50, 0x21, 0x43, 0x07, 0x0e, 0x1c, 0x38, + 0x71, 0x62, 0x44, 0x09, 0x12, 0x24, 0x49, 0x13, 0x26, 0x4d, 0x1b, 0x36, + 0x6d, 0x5a, 0x35, 0x6b, 0x56, 0x2d, 0x5b, 0x37, 0x6f, 0x5e, 0x3d, 0x7b, + 0x76, 0x6c, 0x58, 0x31, 0x63, 0x46, 0x0d, 0x1a, 0x34, 0x69, 0x52, 0x25, + 0x4b, 0x17, 0x2e, 0x5d, 0x3b, 0x77, 0x6e, 0x5c +}; +static uint8_t const rc8[140] = { + 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x47, 0x8e, 0x1c, 0x38, 0x71, 0xe2, + 0xc4, 0x89, 0x12, 0x25, 0x4b, 0x97, 0x2e, 0x5c, 0xb8, 0x70, 0xe0, 0xc0, + 0x81, 0x03, 0x06, 0x0c, 0x19, 0x32, 0x64, 0xc9, 0x92, 0x24, 0x49, 0x93, + 0x26, 0x4d, 0x9b, 0x37, 0x6e, 0xdc, 0xb9, 0x72, 0xe4, 0xc8, 0x90, 0x20, + 0x41, 0x82, 0x05, 0x0a, 0x15, 0x2b, 0x56, 0xad, 0x5b, 0xb6, 0x6d, 0xda, + 0xb5, 0x6b, 0xd6, 0xac, 0x59, 0xb2, 0x65, 0xcb, 0x96, 0x2c, 0x58, 0xb0, + 0x61, 0xc3, 0x87, 0x0f, 0x1f, 0x3e, 0x7d, 0xfb, 0xf6, 0xed, 0xdb, 0xb7, + 0x6f, 0xde, 0xbd, 0x7a, 0xf5, 0xeb, 0xd7, 0xae, 0x5d, 0xba, 0x74, 0xe8, + 0xd1, 0xa2, 0x44, 0x88, 0x10, 0x21, 0x43, 0x86, 0x0d, 0x1b, 0x36, 0x6c, + 0xd8, 0xb1, 0x63, 0xc7, 0x8f, 0x1e, 0x3c, 0x79, 0xf3, 0xe7, 0xce, 0x9c, + 0x39, 0x73, 0xe6, 0xcc, 0x98, 0x31, 0x62, 0xc5, 0x8b, 0x16, 0x2d, 0x5a, + 0xb4, 0x69, 0xd2, 0xa4, 0x48, 0x91, 0x22, 0x45 +}; + +/* Applies the KNOT S-box to four 64-bit words in bit-sliced mode */ +#define knot_sbox64(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint64_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +/* Applies the KNOT S-box to four 32-bit words in bit-sliced mode */ +#define knot_sbox32(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint32_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +static void knot256_permute + (knot256_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b1, b2, b3; + + /* Load the input state into local variables; each row is 64 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x1, x2, x3, b1, b2, b3); + + /* Linear diffusion layer */ + x1 = leftRotate1_64(b1); + x2 = leftRotate8_64(b2); + x3 = leftRotate25_64(b3); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); +#endif +} + +void knot256_permute_6(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc6, rounds); +} + +void knot256_permute_7(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc7, rounds); +} + +void knot384_permute_7(knot384_state_t *state, uint8_t rounds) +{ + const uint8_t *rc = rc7; + uint64_t b2, b4, b6; + uint32_t b3, b5, b7; + + /* Load the input state into local variables; each row is 96 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint32_t x1 = state->W[2]; + uint64_t x2 = state->W[3] | (((uint64_t)(state->W[4])) << 32); + uint32_t x3 = state->W[5]; + uint64_t x4 = state->S[3]; + uint32_t x5 = state->W[8]; + uint64_t x6 = state->W[9] | (((uint64_t)(state->W[10])) << 32); + uint32_t x7 = state->W[11]; +#else + uint64_t x0 = le_load_word64(state->B); + uint32_t x1 = le_load_word32(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 12); + uint32_t x3 = le_load_word32(state->B + 20); + uint64_t x4 = le_load_word64(state->B + 24); + uint32_t x5 = le_load_word32(state->B + 32); + uint64_t x6 = le_load_word64(state->B + 36); + uint32_t x7 = le_load_word32(state->B + 44); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox32(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotateShort_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (32 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + #define leftRotateLong_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | \ + (((uint64_t)(b1)) << ((bits) - 32)) | \ + ((b0) >> (96 - (bits))); \ + (a1) = (uint32_t)(((b0) << ((bits) - 32)) >> 32); \ + } while (0) + leftRotateShort_96(x2, x3, b2, b3, 1); + leftRotateShort_96(x4, x5, b4, b5, 8); + leftRotateLong_96(x6, x7, b6, b7, 55); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->W[2] = x1; + state->W[3] = (uint32_t)x2; + state->W[4] = (uint32_t)(x2 >> 32); + state->W[5] = x3; + state->S[3] = x4; + state->W[8] = x5; + state->W[9] = (uint32_t)x6; + state->W[10] = (uint32_t)(x6 >> 32); + state->W[11] = x7; +#else + le_store_word64(state->B, x0); + le_store_word32(state->B + 8, x1); + le_store_word64(state->B + 12, x2); + le_store_word32(state->B + 20, x3); + le_store_word64(state->B + 24, x4); + le_store_word32(state->B + 32, x5); + le_store_word64(state->B + 36, x6); + le_store_word32(state->B + 44, x7); +#endif +} + +static void knot512_permute + (knot512_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b2, b3, b4, b5, b6, b7; + + /* Load the input state into local variables; each row is 128 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox64(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotate_128(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (64 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + leftRotate_128(x2, x3, b2, b3, 1); + leftRotate_128(x4, x5, b4, b5, 16); + leftRotate_128(x6, x7, b6, b7, 25); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); +#endif +} + +void knot512_permute_7(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc7, rounds); +} + +void knot512_permute_8(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc8, rounds); +} diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.h b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.h new file mode 100644 index 0000000..88a782c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-knot.h @@ -0,0 +1,130 @@ +/* + * 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_KNOT_H +#define LW_INTERNAL_KNOT_H + +#include "internal-util.h" + +/** + * \file internal-knot.h + * \brief Permutations that are used by the KNOT AEAD and hash algorithms. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal state of the KNOT-256 permutation. + */ +typedef union +{ + uint64_t S[4]; /**< Words of the state */ + uint8_t B[32]; /**< Bytes of the state */ + +} knot256_state_t; + +/** + * \brief Internal state of the KNOT-384 permutation. + */ +typedef union +{ + uint64_t S[6]; /**< 64-bit words of the state */ + uint32_t W[12]; /**< 32-bit words of the state */ + uint8_t B[48]; /**< Bytes of the state */ + +} knot384_state_t; + +/** + * \brief Internal state of the KNOT-512 permutation. + */ +typedef union +{ + uint64_t S[8]; /**< Words of the state */ + uint8_t B[64]; /**< Bytes of the state */ + +} knot512_state_t; + +/** + * \brief Permutes the KNOT-256 state, using 6-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 52. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_6(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-256 state, using 7-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_7(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-384 state, using 7-bit round constants. + * + * \param state The KNOT-384 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot384_permute_7(knot384_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 7-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_7(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 8-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 140. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_8(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Generic pointer to a function that performs a KNOT permutation. + * + * \param state Points to the permutation state. + * \param round Number of rounds to perform. + */ +typedef void (*knot_permute_t)(void *state, uint8_t rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/internal-util.h b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/knot-aead.c b/knot/Implementations/crypto_aead/knot128v1/rhys/knot-aead.c new file mode 100644 index 0000000..5825f01 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/knot-aead.c @@ -0,0 +1,503 @@ +/* + * 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 "knot.h" +#include "internal-knot.h" +#include + +aead_cipher_t const knot_aead_128_256_cipher = { + "KNOT-AEAD-128-256", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_256_encrypt, + knot_aead_128_256_decrypt +}; + +aead_cipher_t const knot_aead_128_384_cipher = { + "KNOT-AEAD-128-384", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_384_encrypt, + knot_aead_128_384_decrypt +}; + +aead_cipher_t const knot_aead_192_384_cipher = { + "KNOT-AEAD-192-384", + KNOT_AEAD_192_KEY_SIZE, + KNOT_AEAD_192_NONCE_SIZE, + KNOT_AEAD_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_192_384_encrypt, + knot_aead_192_384_decrypt +}; + +aead_cipher_t const knot_aead_256_512_cipher = { + "KNOT-AEAD-256-512", + KNOT_AEAD_256_KEY_SIZE, + KNOT_AEAD_256_NONCE_SIZE, + KNOT_AEAD_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_256_512_encrypt, + knot_aead_256_512_decrypt +}; + +/** + * \brief Rate for KNOT-AEAD-128-256. + */ +#define KNOT_AEAD_128_256_RATE 8 + +/** + * \brief Rate for KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_384_RATE 24 + +/** + * \brief Rate for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_384_RATE 12 + +/** + * \brief Rate for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_512_RATE 16 + +/** + * \brief Absorbs the associated data into a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be at least 1. + */ +static void knot_aead_absorb_ad + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= rate) { + lw_xor_block((unsigned char *)state, ad, rate); + permute(state, rounds); + ad += rate; + adlen -= rate; + } + rate = (unsigned)adlen; + lw_xor_block((unsigned char *)state, ad, rate); + ((unsigned char *)state)[rate] ^= 0x01; + permute(state, rounds); +} + +/** + * \brief Encrypts plaintext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param c Buffer to receive the ciphertext. + * \param m Buffer containing the plaintext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_encrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *c, const unsigned char *m, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +/** + * \brief Decrypts ciphertext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param m Buffer to receive the plaintext. + * \param c Buffer containing the ciphertext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_decrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *m, const unsigned char *c, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot256_permute_6(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot256_permute_6(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 44); + memcpy(c + mlen, state.B, KNOT_AEAD_192_TAG_SIZE); + return 0; +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_192_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_192_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 44); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_192_TAG_SIZE); +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot512_permute_7(&state, 56); + memcpy(c + mlen, state.B, KNOT_AEAD_256_TAG_SIZE); + return 0; +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_256_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_256_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot512_permute_7(&state, 56); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_256_TAG_SIZE); +} diff --git a/knot/Implementations/crypto_aead/knot128v1/rhys/knot.h b/knot/Implementations/crypto_aead/knot128v1/rhys/knot.h new file mode 100644 index 0000000..e2c5198 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v1/rhys/knot.h @@ -0,0 +1,459 @@ +/* + * 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_KNOT_H +#define LWCRYPTO_KNOT_H + +#include "aead-common.h" + +/** + * \file knot.h + * \brief KNOT authenticated encryption and hash algorithms. + * + * KNOT is a family of authenticated encryption and hash algorithms built + * around a permutation and the MonkeyDuplex sponge construction. The + * family members are: + * + * \li KNOT-AEAD-128-256 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 256-bit permutation. This is the primary + * encryption member of the family. + * \li KNOT-AEAD-128-384 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-192-384 with a 192-bit key, a 192-bit nonce, and a + * 192-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-256-512 with a 256-bit key, a 256-bit nonce, and a + * 256-bit tag, built around a 512-bit permutation. + * \li KNOT-HASH-256-256 with a 256-bit hash output, built around a + * 256-bit permutation. This is the primary hashing member of the family. + * \li KNOT-HASH-256-384 with a 256-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-384-384 with a 384-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-512-512 with a 512-bit hash output, built around a + * 512-bit permutation. + * + * References: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/knot-spec-round.pdf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-128-256 and + * KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-256-256 and KNOT-HASH-256-384. + */ +#define KNOT_HASH_256_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-384-384. + */ +#define KNOT_HASH_384_SIZE 48 + +/** + * \brief Size of the hash for KNOT-HASH-512-512. + */ +#define KNOT_HASH_512_SIZE 64 + +/** + * \brief Meta-information block for the KNOT-AEAD-128-256 cipher. + */ +extern aead_cipher_t const knot_aead_128_256_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-128-384 cipher. + */ +extern aead_cipher_t const knot_aead_128_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-192-384 cipher. + */ +extern aead_cipher_t const knot_aead_192_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-256-512 cipher. + */ +extern aead_cipher_t const knot_aead_256_512_cipher; + +/** + * \brief Meta-information block for the KNOT-HASH-256-256 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_256_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-256-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-384-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_384_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-512-512 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_512_512_algorithm; + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_256_decrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_256_encrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_384_decrypt() + */ +int knot_aead_128_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_384_encrypt() + */ +int knot_aead_128_384_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); + + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_192_384_decrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_192_384_encrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_256_512_decrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_256_512_encrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-256. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_256 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-384-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_384_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 knot_hash_384_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-512-512. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_512_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 knot_hash_512_512 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.c b/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.h b/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/api.h b/knot/Implementations/crypto_aead/knot128v2/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/encrypt.c b/knot/Implementations/crypto_aead/knot128v2/rhys/encrypt.c new file mode 100644 index 0000000..e80d720 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "knot.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 knot_aead_128_384_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 knot_aead_128_384_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.c b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.c new file mode 100644 index 0000000..3486e6e --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.c @@ -0,0 +1,297 @@ +/* + * 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 "internal-knot.h" + +/* Round constants for the KNOT-256, KNOT-384, and KNOT-512 permutations */ +static uint8_t const rc6[52] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x21, 0x03, 0x06, 0x0c, 0x18, 0x31, 0x22, + 0x05, 0x0a, 0x14, 0x29, 0x13, 0x27, 0x0f, 0x1e, 0x3d, 0x3a, 0x34, 0x28, + 0x11, 0x23, 0x07, 0x0e, 0x1c, 0x39, 0x32, 0x24, 0x09, 0x12, 0x25, 0x0b, + 0x16, 0x2d, 0x1b, 0x37, 0x2e, 0x1d, 0x3b, 0x36, 0x2c, 0x19, 0x33, 0x26, + 0x0d, 0x1a, 0x35, 0x2a +}; +static uint8_t const rc7[104] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x41, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x61, 0x42, 0x05, 0x0a, 0x14, 0x28, 0x51, 0x23, 0x47, 0x0f, 0x1e, 0x3c, + 0x79, 0x72, 0x64, 0x48, 0x11, 0x22, 0x45, 0x0b, 0x16, 0x2c, 0x59, 0x33, + 0x67, 0x4e, 0x1d, 0x3a, 0x75, 0x6a, 0x54, 0x29, 0x53, 0x27, 0x4f, 0x1f, + 0x3e, 0x7d, 0x7a, 0x74, 0x68, 0x50, 0x21, 0x43, 0x07, 0x0e, 0x1c, 0x38, + 0x71, 0x62, 0x44, 0x09, 0x12, 0x24, 0x49, 0x13, 0x26, 0x4d, 0x1b, 0x36, + 0x6d, 0x5a, 0x35, 0x6b, 0x56, 0x2d, 0x5b, 0x37, 0x6f, 0x5e, 0x3d, 0x7b, + 0x76, 0x6c, 0x58, 0x31, 0x63, 0x46, 0x0d, 0x1a, 0x34, 0x69, 0x52, 0x25, + 0x4b, 0x17, 0x2e, 0x5d, 0x3b, 0x77, 0x6e, 0x5c +}; +static uint8_t const rc8[140] = { + 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x47, 0x8e, 0x1c, 0x38, 0x71, 0xe2, + 0xc4, 0x89, 0x12, 0x25, 0x4b, 0x97, 0x2e, 0x5c, 0xb8, 0x70, 0xe0, 0xc0, + 0x81, 0x03, 0x06, 0x0c, 0x19, 0x32, 0x64, 0xc9, 0x92, 0x24, 0x49, 0x93, + 0x26, 0x4d, 0x9b, 0x37, 0x6e, 0xdc, 0xb9, 0x72, 0xe4, 0xc8, 0x90, 0x20, + 0x41, 0x82, 0x05, 0x0a, 0x15, 0x2b, 0x56, 0xad, 0x5b, 0xb6, 0x6d, 0xda, + 0xb5, 0x6b, 0xd6, 0xac, 0x59, 0xb2, 0x65, 0xcb, 0x96, 0x2c, 0x58, 0xb0, + 0x61, 0xc3, 0x87, 0x0f, 0x1f, 0x3e, 0x7d, 0xfb, 0xf6, 0xed, 0xdb, 0xb7, + 0x6f, 0xde, 0xbd, 0x7a, 0xf5, 0xeb, 0xd7, 0xae, 0x5d, 0xba, 0x74, 0xe8, + 0xd1, 0xa2, 0x44, 0x88, 0x10, 0x21, 0x43, 0x86, 0x0d, 0x1b, 0x36, 0x6c, + 0xd8, 0xb1, 0x63, 0xc7, 0x8f, 0x1e, 0x3c, 0x79, 0xf3, 0xe7, 0xce, 0x9c, + 0x39, 0x73, 0xe6, 0xcc, 0x98, 0x31, 0x62, 0xc5, 0x8b, 0x16, 0x2d, 0x5a, + 0xb4, 0x69, 0xd2, 0xa4, 0x48, 0x91, 0x22, 0x45 +}; + +/* Applies the KNOT S-box to four 64-bit words in bit-sliced mode */ +#define knot_sbox64(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint64_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +/* Applies the KNOT S-box to four 32-bit words in bit-sliced mode */ +#define knot_sbox32(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint32_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +static void knot256_permute + (knot256_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b1, b2, b3; + + /* Load the input state into local variables; each row is 64 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x1, x2, x3, b1, b2, b3); + + /* Linear diffusion layer */ + x1 = leftRotate1_64(b1); + x2 = leftRotate8_64(b2); + x3 = leftRotate25_64(b3); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); +#endif +} + +void knot256_permute_6(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc6, rounds); +} + +void knot256_permute_7(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc7, rounds); +} + +void knot384_permute_7(knot384_state_t *state, uint8_t rounds) +{ + const uint8_t *rc = rc7; + uint64_t b2, b4, b6; + uint32_t b3, b5, b7; + + /* Load the input state into local variables; each row is 96 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint32_t x1 = state->W[2]; + uint64_t x2 = state->W[3] | (((uint64_t)(state->W[4])) << 32); + uint32_t x3 = state->W[5]; + uint64_t x4 = state->S[3]; + uint32_t x5 = state->W[8]; + uint64_t x6 = state->W[9] | (((uint64_t)(state->W[10])) << 32); + uint32_t x7 = state->W[11]; +#else + uint64_t x0 = le_load_word64(state->B); + uint32_t x1 = le_load_word32(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 12); + uint32_t x3 = le_load_word32(state->B + 20); + uint64_t x4 = le_load_word64(state->B + 24); + uint32_t x5 = le_load_word32(state->B + 32); + uint64_t x6 = le_load_word64(state->B + 36); + uint32_t x7 = le_load_word32(state->B + 44); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox32(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotateShort_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (32 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + #define leftRotateLong_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | \ + (((uint64_t)(b1)) << ((bits) - 32)) | \ + ((b0) >> (96 - (bits))); \ + (a1) = (uint32_t)(((b0) << ((bits) - 32)) >> 32); \ + } while (0) + leftRotateShort_96(x2, x3, b2, b3, 1); + leftRotateShort_96(x4, x5, b4, b5, 8); + leftRotateLong_96(x6, x7, b6, b7, 55); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->W[2] = x1; + state->W[3] = (uint32_t)x2; + state->W[4] = (uint32_t)(x2 >> 32); + state->W[5] = x3; + state->S[3] = x4; + state->W[8] = x5; + state->W[9] = (uint32_t)x6; + state->W[10] = (uint32_t)(x6 >> 32); + state->W[11] = x7; +#else + le_store_word64(state->B, x0); + le_store_word32(state->B + 8, x1); + le_store_word64(state->B + 12, x2); + le_store_word32(state->B + 20, x3); + le_store_word64(state->B + 24, x4); + le_store_word32(state->B + 32, x5); + le_store_word64(state->B + 36, x6); + le_store_word32(state->B + 44, x7); +#endif +} + +static void knot512_permute + (knot512_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b2, b3, b4, b5, b6, b7; + + /* Load the input state into local variables; each row is 128 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox64(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotate_128(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (64 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + leftRotate_128(x2, x3, b2, b3, 1); + leftRotate_128(x4, x5, b4, b5, 16); + leftRotate_128(x6, x7, b6, b7, 25); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); +#endif +} + +void knot512_permute_7(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc7, rounds); +} + +void knot512_permute_8(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc8, rounds); +} diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.h b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.h new file mode 100644 index 0000000..88a782c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-knot.h @@ -0,0 +1,130 @@ +/* + * 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_KNOT_H +#define LW_INTERNAL_KNOT_H + +#include "internal-util.h" + +/** + * \file internal-knot.h + * \brief Permutations that are used by the KNOT AEAD and hash algorithms. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal state of the KNOT-256 permutation. + */ +typedef union +{ + uint64_t S[4]; /**< Words of the state */ + uint8_t B[32]; /**< Bytes of the state */ + +} knot256_state_t; + +/** + * \brief Internal state of the KNOT-384 permutation. + */ +typedef union +{ + uint64_t S[6]; /**< 64-bit words of the state */ + uint32_t W[12]; /**< 32-bit words of the state */ + uint8_t B[48]; /**< Bytes of the state */ + +} knot384_state_t; + +/** + * \brief Internal state of the KNOT-512 permutation. + */ +typedef union +{ + uint64_t S[8]; /**< Words of the state */ + uint8_t B[64]; /**< Bytes of the state */ + +} knot512_state_t; + +/** + * \brief Permutes the KNOT-256 state, using 6-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 52. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_6(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-256 state, using 7-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_7(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-384 state, using 7-bit round constants. + * + * \param state The KNOT-384 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot384_permute_7(knot384_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 7-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_7(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 8-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 140. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_8(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Generic pointer to a function that performs a KNOT permutation. + * + * \param state Points to the permutation state. + * \param round Number of rounds to perform. + */ +typedef void (*knot_permute_t)(void *state, uint8_t rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/internal-util.h b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/knot-aead.c b/knot/Implementations/crypto_aead/knot128v2/rhys/knot-aead.c new file mode 100644 index 0000000..5825f01 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/knot-aead.c @@ -0,0 +1,503 @@ +/* + * 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 "knot.h" +#include "internal-knot.h" +#include + +aead_cipher_t const knot_aead_128_256_cipher = { + "KNOT-AEAD-128-256", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_256_encrypt, + knot_aead_128_256_decrypt +}; + +aead_cipher_t const knot_aead_128_384_cipher = { + "KNOT-AEAD-128-384", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_384_encrypt, + knot_aead_128_384_decrypt +}; + +aead_cipher_t const knot_aead_192_384_cipher = { + "KNOT-AEAD-192-384", + KNOT_AEAD_192_KEY_SIZE, + KNOT_AEAD_192_NONCE_SIZE, + KNOT_AEAD_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_192_384_encrypt, + knot_aead_192_384_decrypt +}; + +aead_cipher_t const knot_aead_256_512_cipher = { + "KNOT-AEAD-256-512", + KNOT_AEAD_256_KEY_SIZE, + KNOT_AEAD_256_NONCE_SIZE, + KNOT_AEAD_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_256_512_encrypt, + knot_aead_256_512_decrypt +}; + +/** + * \brief Rate for KNOT-AEAD-128-256. + */ +#define KNOT_AEAD_128_256_RATE 8 + +/** + * \brief Rate for KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_384_RATE 24 + +/** + * \brief Rate for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_384_RATE 12 + +/** + * \brief Rate for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_512_RATE 16 + +/** + * \brief Absorbs the associated data into a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be at least 1. + */ +static void knot_aead_absorb_ad + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= rate) { + lw_xor_block((unsigned char *)state, ad, rate); + permute(state, rounds); + ad += rate; + adlen -= rate; + } + rate = (unsigned)adlen; + lw_xor_block((unsigned char *)state, ad, rate); + ((unsigned char *)state)[rate] ^= 0x01; + permute(state, rounds); +} + +/** + * \brief Encrypts plaintext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param c Buffer to receive the ciphertext. + * \param m Buffer containing the plaintext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_encrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *c, const unsigned char *m, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +/** + * \brief Decrypts ciphertext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param m Buffer to receive the plaintext. + * \param c Buffer containing the ciphertext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_decrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *m, const unsigned char *c, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot256_permute_6(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot256_permute_6(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 44); + memcpy(c + mlen, state.B, KNOT_AEAD_192_TAG_SIZE); + return 0; +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_192_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_192_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 44); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_192_TAG_SIZE); +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot512_permute_7(&state, 56); + memcpy(c + mlen, state.B, KNOT_AEAD_256_TAG_SIZE); + return 0; +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_256_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_256_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot512_permute_7(&state, 56); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_256_TAG_SIZE); +} diff --git a/knot/Implementations/crypto_aead/knot128v2/rhys/knot.h b/knot/Implementations/crypto_aead/knot128v2/rhys/knot.h new file mode 100644 index 0000000..e2c5198 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot128v2/rhys/knot.h @@ -0,0 +1,459 @@ +/* + * 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_KNOT_H +#define LWCRYPTO_KNOT_H + +#include "aead-common.h" + +/** + * \file knot.h + * \brief KNOT authenticated encryption and hash algorithms. + * + * KNOT is a family of authenticated encryption and hash algorithms built + * around a permutation and the MonkeyDuplex sponge construction. The + * family members are: + * + * \li KNOT-AEAD-128-256 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 256-bit permutation. This is the primary + * encryption member of the family. + * \li KNOT-AEAD-128-384 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-192-384 with a 192-bit key, a 192-bit nonce, and a + * 192-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-256-512 with a 256-bit key, a 256-bit nonce, and a + * 256-bit tag, built around a 512-bit permutation. + * \li KNOT-HASH-256-256 with a 256-bit hash output, built around a + * 256-bit permutation. This is the primary hashing member of the family. + * \li KNOT-HASH-256-384 with a 256-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-384-384 with a 384-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-512-512 with a 512-bit hash output, built around a + * 512-bit permutation. + * + * References: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/knot-spec-round.pdf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-128-256 and + * KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-256-256 and KNOT-HASH-256-384. + */ +#define KNOT_HASH_256_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-384-384. + */ +#define KNOT_HASH_384_SIZE 48 + +/** + * \brief Size of the hash for KNOT-HASH-512-512. + */ +#define KNOT_HASH_512_SIZE 64 + +/** + * \brief Meta-information block for the KNOT-AEAD-128-256 cipher. + */ +extern aead_cipher_t const knot_aead_128_256_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-128-384 cipher. + */ +extern aead_cipher_t const knot_aead_128_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-192-384 cipher. + */ +extern aead_cipher_t const knot_aead_192_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-256-512 cipher. + */ +extern aead_cipher_t const knot_aead_256_512_cipher; + +/** + * \brief Meta-information block for the KNOT-HASH-256-256 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_256_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-256-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-384-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_384_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-512-512 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_512_512_algorithm; + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_256_decrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_256_encrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_384_decrypt() + */ +int knot_aead_128_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_384_encrypt() + */ +int knot_aead_128_384_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); + + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_192_384_decrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_192_384_encrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_256_512_decrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_256_512_encrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-256. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_256 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-384-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_384_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 knot_hash_384_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-512-512. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_512_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 knot_hash_512_512 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot192/rhys/aead-common.c b/knot/Implementations/crypto_aead/knot192/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/knot/Implementations/crypto_aead/knot192/rhys/aead-common.h b/knot/Implementations/crypto_aead/knot192/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/knot/Implementations/crypto_aead/knot192/rhys/api.h b/knot/Implementations/crypto_aead/knot192/rhys/api.h new file mode 100644 index 0000000..c340ebc --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 24 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 24 +#define CRYPTO_ABYTES 24 +#define CRYPTO_NOOVERLAP 1 diff --git a/knot/Implementations/crypto_aead/knot192/rhys/encrypt.c b/knot/Implementations/crypto_aead/knot192/rhys/encrypt.c new file mode 100644 index 0000000..7d9ae8b --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "knot.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 knot_aead_192_384_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 knot_aead_192_384_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.c b/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.c new file mode 100644 index 0000000..3486e6e --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.c @@ -0,0 +1,297 @@ +/* + * 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 "internal-knot.h" + +/* Round constants for the KNOT-256, KNOT-384, and KNOT-512 permutations */ +static uint8_t const rc6[52] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x21, 0x03, 0x06, 0x0c, 0x18, 0x31, 0x22, + 0x05, 0x0a, 0x14, 0x29, 0x13, 0x27, 0x0f, 0x1e, 0x3d, 0x3a, 0x34, 0x28, + 0x11, 0x23, 0x07, 0x0e, 0x1c, 0x39, 0x32, 0x24, 0x09, 0x12, 0x25, 0x0b, + 0x16, 0x2d, 0x1b, 0x37, 0x2e, 0x1d, 0x3b, 0x36, 0x2c, 0x19, 0x33, 0x26, + 0x0d, 0x1a, 0x35, 0x2a +}; +static uint8_t const rc7[104] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x41, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x61, 0x42, 0x05, 0x0a, 0x14, 0x28, 0x51, 0x23, 0x47, 0x0f, 0x1e, 0x3c, + 0x79, 0x72, 0x64, 0x48, 0x11, 0x22, 0x45, 0x0b, 0x16, 0x2c, 0x59, 0x33, + 0x67, 0x4e, 0x1d, 0x3a, 0x75, 0x6a, 0x54, 0x29, 0x53, 0x27, 0x4f, 0x1f, + 0x3e, 0x7d, 0x7a, 0x74, 0x68, 0x50, 0x21, 0x43, 0x07, 0x0e, 0x1c, 0x38, + 0x71, 0x62, 0x44, 0x09, 0x12, 0x24, 0x49, 0x13, 0x26, 0x4d, 0x1b, 0x36, + 0x6d, 0x5a, 0x35, 0x6b, 0x56, 0x2d, 0x5b, 0x37, 0x6f, 0x5e, 0x3d, 0x7b, + 0x76, 0x6c, 0x58, 0x31, 0x63, 0x46, 0x0d, 0x1a, 0x34, 0x69, 0x52, 0x25, + 0x4b, 0x17, 0x2e, 0x5d, 0x3b, 0x77, 0x6e, 0x5c +}; +static uint8_t const rc8[140] = { + 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x47, 0x8e, 0x1c, 0x38, 0x71, 0xe2, + 0xc4, 0x89, 0x12, 0x25, 0x4b, 0x97, 0x2e, 0x5c, 0xb8, 0x70, 0xe0, 0xc0, + 0x81, 0x03, 0x06, 0x0c, 0x19, 0x32, 0x64, 0xc9, 0x92, 0x24, 0x49, 0x93, + 0x26, 0x4d, 0x9b, 0x37, 0x6e, 0xdc, 0xb9, 0x72, 0xe4, 0xc8, 0x90, 0x20, + 0x41, 0x82, 0x05, 0x0a, 0x15, 0x2b, 0x56, 0xad, 0x5b, 0xb6, 0x6d, 0xda, + 0xb5, 0x6b, 0xd6, 0xac, 0x59, 0xb2, 0x65, 0xcb, 0x96, 0x2c, 0x58, 0xb0, + 0x61, 0xc3, 0x87, 0x0f, 0x1f, 0x3e, 0x7d, 0xfb, 0xf6, 0xed, 0xdb, 0xb7, + 0x6f, 0xde, 0xbd, 0x7a, 0xf5, 0xeb, 0xd7, 0xae, 0x5d, 0xba, 0x74, 0xe8, + 0xd1, 0xa2, 0x44, 0x88, 0x10, 0x21, 0x43, 0x86, 0x0d, 0x1b, 0x36, 0x6c, + 0xd8, 0xb1, 0x63, 0xc7, 0x8f, 0x1e, 0x3c, 0x79, 0xf3, 0xe7, 0xce, 0x9c, + 0x39, 0x73, 0xe6, 0xcc, 0x98, 0x31, 0x62, 0xc5, 0x8b, 0x16, 0x2d, 0x5a, + 0xb4, 0x69, 0xd2, 0xa4, 0x48, 0x91, 0x22, 0x45 +}; + +/* Applies the KNOT S-box to four 64-bit words in bit-sliced mode */ +#define knot_sbox64(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint64_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +/* Applies the KNOT S-box to four 32-bit words in bit-sliced mode */ +#define knot_sbox32(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint32_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +static void knot256_permute + (knot256_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b1, b2, b3; + + /* Load the input state into local variables; each row is 64 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x1, x2, x3, b1, b2, b3); + + /* Linear diffusion layer */ + x1 = leftRotate1_64(b1); + x2 = leftRotate8_64(b2); + x3 = leftRotate25_64(b3); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); +#endif +} + +void knot256_permute_6(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc6, rounds); +} + +void knot256_permute_7(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc7, rounds); +} + +void knot384_permute_7(knot384_state_t *state, uint8_t rounds) +{ + const uint8_t *rc = rc7; + uint64_t b2, b4, b6; + uint32_t b3, b5, b7; + + /* Load the input state into local variables; each row is 96 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint32_t x1 = state->W[2]; + uint64_t x2 = state->W[3] | (((uint64_t)(state->W[4])) << 32); + uint32_t x3 = state->W[5]; + uint64_t x4 = state->S[3]; + uint32_t x5 = state->W[8]; + uint64_t x6 = state->W[9] | (((uint64_t)(state->W[10])) << 32); + uint32_t x7 = state->W[11]; +#else + uint64_t x0 = le_load_word64(state->B); + uint32_t x1 = le_load_word32(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 12); + uint32_t x3 = le_load_word32(state->B + 20); + uint64_t x4 = le_load_word64(state->B + 24); + uint32_t x5 = le_load_word32(state->B + 32); + uint64_t x6 = le_load_word64(state->B + 36); + uint32_t x7 = le_load_word32(state->B + 44); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox32(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotateShort_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (32 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + #define leftRotateLong_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | \ + (((uint64_t)(b1)) << ((bits) - 32)) | \ + ((b0) >> (96 - (bits))); \ + (a1) = (uint32_t)(((b0) << ((bits) - 32)) >> 32); \ + } while (0) + leftRotateShort_96(x2, x3, b2, b3, 1); + leftRotateShort_96(x4, x5, b4, b5, 8); + leftRotateLong_96(x6, x7, b6, b7, 55); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->W[2] = x1; + state->W[3] = (uint32_t)x2; + state->W[4] = (uint32_t)(x2 >> 32); + state->W[5] = x3; + state->S[3] = x4; + state->W[8] = x5; + state->W[9] = (uint32_t)x6; + state->W[10] = (uint32_t)(x6 >> 32); + state->W[11] = x7; +#else + le_store_word64(state->B, x0); + le_store_word32(state->B + 8, x1); + le_store_word64(state->B + 12, x2); + le_store_word32(state->B + 20, x3); + le_store_word64(state->B + 24, x4); + le_store_word32(state->B + 32, x5); + le_store_word64(state->B + 36, x6); + le_store_word32(state->B + 44, x7); +#endif +} + +static void knot512_permute + (knot512_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b2, b3, b4, b5, b6, b7; + + /* Load the input state into local variables; each row is 128 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox64(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotate_128(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (64 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + leftRotate_128(x2, x3, b2, b3, 1); + leftRotate_128(x4, x5, b4, b5, 16); + leftRotate_128(x6, x7, b6, b7, 25); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); +#endif +} + +void knot512_permute_7(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc7, rounds); +} + +void knot512_permute_8(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc8, rounds); +} diff --git a/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.h b/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.h new file mode 100644 index 0000000..88a782c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/internal-knot.h @@ -0,0 +1,130 @@ +/* + * 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_KNOT_H +#define LW_INTERNAL_KNOT_H + +#include "internal-util.h" + +/** + * \file internal-knot.h + * \brief Permutations that are used by the KNOT AEAD and hash algorithms. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal state of the KNOT-256 permutation. + */ +typedef union +{ + uint64_t S[4]; /**< Words of the state */ + uint8_t B[32]; /**< Bytes of the state */ + +} knot256_state_t; + +/** + * \brief Internal state of the KNOT-384 permutation. + */ +typedef union +{ + uint64_t S[6]; /**< 64-bit words of the state */ + uint32_t W[12]; /**< 32-bit words of the state */ + uint8_t B[48]; /**< Bytes of the state */ + +} knot384_state_t; + +/** + * \brief Internal state of the KNOT-512 permutation. + */ +typedef union +{ + uint64_t S[8]; /**< Words of the state */ + uint8_t B[64]; /**< Bytes of the state */ + +} knot512_state_t; + +/** + * \brief Permutes the KNOT-256 state, using 6-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 52. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_6(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-256 state, using 7-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_7(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-384 state, using 7-bit round constants. + * + * \param state The KNOT-384 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot384_permute_7(knot384_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 7-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_7(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 8-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 140. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_8(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Generic pointer to a function that performs a KNOT permutation. + * + * \param state Points to the permutation state. + * \param round Number of rounds to perform. + */ +typedef void (*knot_permute_t)(void *state, uint8_t rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot192/rhys/internal-util.h b/knot/Implementations/crypto_aead/knot192/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/knot/Implementations/crypto_aead/knot192/rhys/knot-aead.c b/knot/Implementations/crypto_aead/knot192/rhys/knot-aead.c new file mode 100644 index 0000000..5825f01 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/knot-aead.c @@ -0,0 +1,503 @@ +/* + * 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 "knot.h" +#include "internal-knot.h" +#include + +aead_cipher_t const knot_aead_128_256_cipher = { + "KNOT-AEAD-128-256", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_256_encrypt, + knot_aead_128_256_decrypt +}; + +aead_cipher_t const knot_aead_128_384_cipher = { + "KNOT-AEAD-128-384", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_384_encrypt, + knot_aead_128_384_decrypt +}; + +aead_cipher_t const knot_aead_192_384_cipher = { + "KNOT-AEAD-192-384", + KNOT_AEAD_192_KEY_SIZE, + KNOT_AEAD_192_NONCE_SIZE, + KNOT_AEAD_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_192_384_encrypt, + knot_aead_192_384_decrypt +}; + +aead_cipher_t const knot_aead_256_512_cipher = { + "KNOT-AEAD-256-512", + KNOT_AEAD_256_KEY_SIZE, + KNOT_AEAD_256_NONCE_SIZE, + KNOT_AEAD_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_256_512_encrypt, + knot_aead_256_512_decrypt +}; + +/** + * \brief Rate for KNOT-AEAD-128-256. + */ +#define KNOT_AEAD_128_256_RATE 8 + +/** + * \brief Rate for KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_384_RATE 24 + +/** + * \brief Rate for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_384_RATE 12 + +/** + * \brief Rate for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_512_RATE 16 + +/** + * \brief Absorbs the associated data into a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be at least 1. + */ +static void knot_aead_absorb_ad + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= rate) { + lw_xor_block((unsigned char *)state, ad, rate); + permute(state, rounds); + ad += rate; + adlen -= rate; + } + rate = (unsigned)adlen; + lw_xor_block((unsigned char *)state, ad, rate); + ((unsigned char *)state)[rate] ^= 0x01; + permute(state, rounds); +} + +/** + * \brief Encrypts plaintext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param c Buffer to receive the ciphertext. + * \param m Buffer containing the plaintext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_encrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *c, const unsigned char *m, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +/** + * \brief Decrypts ciphertext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param m Buffer to receive the plaintext. + * \param c Buffer containing the ciphertext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_decrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *m, const unsigned char *c, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot256_permute_6(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot256_permute_6(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 44); + memcpy(c + mlen, state.B, KNOT_AEAD_192_TAG_SIZE); + return 0; +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_192_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_192_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 44); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_192_TAG_SIZE); +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot512_permute_7(&state, 56); + memcpy(c + mlen, state.B, KNOT_AEAD_256_TAG_SIZE); + return 0; +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_256_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_256_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot512_permute_7(&state, 56); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_256_TAG_SIZE); +} diff --git a/knot/Implementations/crypto_aead/knot192/rhys/knot.h b/knot/Implementations/crypto_aead/knot192/rhys/knot.h new file mode 100644 index 0000000..e2c5198 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot192/rhys/knot.h @@ -0,0 +1,459 @@ +/* + * 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_KNOT_H +#define LWCRYPTO_KNOT_H + +#include "aead-common.h" + +/** + * \file knot.h + * \brief KNOT authenticated encryption and hash algorithms. + * + * KNOT is a family of authenticated encryption and hash algorithms built + * around a permutation and the MonkeyDuplex sponge construction. The + * family members are: + * + * \li KNOT-AEAD-128-256 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 256-bit permutation. This is the primary + * encryption member of the family. + * \li KNOT-AEAD-128-384 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-192-384 with a 192-bit key, a 192-bit nonce, and a + * 192-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-256-512 with a 256-bit key, a 256-bit nonce, and a + * 256-bit tag, built around a 512-bit permutation. + * \li KNOT-HASH-256-256 with a 256-bit hash output, built around a + * 256-bit permutation. This is the primary hashing member of the family. + * \li KNOT-HASH-256-384 with a 256-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-384-384 with a 384-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-512-512 with a 512-bit hash output, built around a + * 512-bit permutation. + * + * References: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/knot-spec-round.pdf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-128-256 and + * KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-256-256 and KNOT-HASH-256-384. + */ +#define KNOT_HASH_256_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-384-384. + */ +#define KNOT_HASH_384_SIZE 48 + +/** + * \brief Size of the hash for KNOT-HASH-512-512. + */ +#define KNOT_HASH_512_SIZE 64 + +/** + * \brief Meta-information block for the KNOT-AEAD-128-256 cipher. + */ +extern aead_cipher_t const knot_aead_128_256_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-128-384 cipher. + */ +extern aead_cipher_t const knot_aead_128_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-192-384 cipher. + */ +extern aead_cipher_t const knot_aead_192_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-256-512 cipher. + */ +extern aead_cipher_t const knot_aead_256_512_cipher; + +/** + * \brief Meta-information block for the KNOT-HASH-256-256 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_256_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-256-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-384-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_384_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-512-512 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_512_512_algorithm; + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_256_decrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_256_encrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_384_decrypt() + */ +int knot_aead_128_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_384_encrypt() + */ +int knot_aead_128_384_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); + + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_192_384_decrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_192_384_encrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_256_512_decrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_256_512_encrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-256. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_256 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-384-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_384_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 knot_hash_384_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-512-512. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_512_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 knot_hash_512_512 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot256/rhys/aead-common.c b/knot/Implementations/crypto_aead/knot256/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/knot/Implementations/crypto_aead/knot256/rhys/aead-common.h b/knot/Implementations/crypto_aead/knot256/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/knot/Implementations/crypto_aead/knot256/rhys/api.h b/knot/Implementations/crypto_aead/knot256/rhys/api.h new file mode 100644 index 0000000..c11fc10 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 32 +#define CRYPTO_ABYTES 32 +#define CRYPTO_NOOVERLAP 1 diff --git a/knot/Implementations/crypto_aead/knot256/rhys/encrypt.c b/knot/Implementations/crypto_aead/knot256/rhys/encrypt.c new file mode 100644 index 0000000..8f6225a --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "knot.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 knot_aead_256_512_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 knot_aead_256_512_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.c b/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.c new file mode 100644 index 0000000..3486e6e --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.c @@ -0,0 +1,297 @@ +/* + * 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 "internal-knot.h" + +/* Round constants for the KNOT-256, KNOT-384, and KNOT-512 permutations */ +static uint8_t const rc6[52] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x21, 0x03, 0x06, 0x0c, 0x18, 0x31, 0x22, + 0x05, 0x0a, 0x14, 0x29, 0x13, 0x27, 0x0f, 0x1e, 0x3d, 0x3a, 0x34, 0x28, + 0x11, 0x23, 0x07, 0x0e, 0x1c, 0x39, 0x32, 0x24, 0x09, 0x12, 0x25, 0x0b, + 0x16, 0x2d, 0x1b, 0x37, 0x2e, 0x1d, 0x3b, 0x36, 0x2c, 0x19, 0x33, 0x26, + 0x0d, 0x1a, 0x35, 0x2a +}; +static uint8_t const rc7[104] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x41, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x61, 0x42, 0x05, 0x0a, 0x14, 0x28, 0x51, 0x23, 0x47, 0x0f, 0x1e, 0x3c, + 0x79, 0x72, 0x64, 0x48, 0x11, 0x22, 0x45, 0x0b, 0x16, 0x2c, 0x59, 0x33, + 0x67, 0x4e, 0x1d, 0x3a, 0x75, 0x6a, 0x54, 0x29, 0x53, 0x27, 0x4f, 0x1f, + 0x3e, 0x7d, 0x7a, 0x74, 0x68, 0x50, 0x21, 0x43, 0x07, 0x0e, 0x1c, 0x38, + 0x71, 0x62, 0x44, 0x09, 0x12, 0x24, 0x49, 0x13, 0x26, 0x4d, 0x1b, 0x36, + 0x6d, 0x5a, 0x35, 0x6b, 0x56, 0x2d, 0x5b, 0x37, 0x6f, 0x5e, 0x3d, 0x7b, + 0x76, 0x6c, 0x58, 0x31, 0x63, 0x46, 0x0d, 0x1a, 0x34, 0x69, 0x52, 0x25, + 0x4b, 0x17, 0x2e, 0x5d, 0x3b, 0x77, 0x6e, 0x5c +}; +static uint8_t const rc8[140] = { + 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x47, 0x8e, 0x1c, 0x38, 0x71, 0xe2, + 0xc4, 0x89, 0x12, 0x25, 0x4b, 0x97, 0x2e, 0x5c, 0xb8, 0x70, 0xe0, 0xc0, + 0x81, 0x03, 0x06, 0x0c, 0x19, 0x32, 0x64, 0xc9, 0x92, 0x24, 0x49, 0x93, + 0x26, 0x4d, 0x9b, 0x37, 0x6e, 0xdc, 0xb9, 0x72, 0xe4, 0xc8, 0x90, 0x20, + 0x41, 0x82, 0x05, 0x0a, 0x15, 0x2b, 0x56, 0xad, 0x5b, 0xb6, 0x6d, 0xda, + 0xb5, 0x6b, 0xd6, 0xac, 0x59, 0xb2, 0x65, 0xcb, 0x96, 0x2c, 0x58, 0xb0, + 0x61, 0xc3, 0x87, 0x0f, 0x1f, 0x3e, 0x7d, 0xfb, 0xf6, 0xed, 0xdb, 0xb7, + 0x6f, 0xde, 0xbd, 0x7a, 0xf5, 0xeb, 0xd7, 0xae, 0x5d, 0xba, 0x74, 0xe8, + 0xd1, 0xa2, 0x44, 0x88, 0x10, 0x21, 0x43, 0x86, 0x0d, 0x1b, 0x36, 0x6c, + 0xd8, 0xb1, 0x63, 0xc7, 0x8f, 0x1e, 0x3c, 0x79, 0xf3, 0xe7, 0xce, 0x9c, + 0x39, 0x73, 0xe6, 0xcc, 0x98, 0x31, 0x62, 0xc5, 0x8b, 0x16, 0x2d, 0x5a, + 0xb4, 0x69, 0xd2, 0xa4, 0x48, 0x91, 0x22, 0x45 +}; + +/* Applies the KNOT S-box to four 64-bit words in bit-sliced mode */ +#define knot_sbox64(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint64_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +/* Applies the KNOT S-box to four 32-bit words in bit-sliced mode */ +#define knot_sbox32(a0, a1, a2, a3, b1, b2, b3) \ + do { \ + uint32_t t1, t3, t6; \ + t1 = ~(a0); \ + t3 = (a2) ^ ((a1) & t1); \ + (b3) = (a3) ^ t3; \ + t6 = (a3) ^ t1; \ + (b2) = ((a1) | (a2)) ^ t6; \ + t1 = (a1) ^ (a3); \ + (a0) = t1 ^ (t3 & t6); \ + (b1) = t3 ^ ((b2) & t1); \ + } while (0) + +static void knot256_permute + (knot256_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b1, b2, b3; + + /* Load the input state into local variables; each row is 64 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x1, x2, x3, b1, b2, b3); + + /* Linear diffusion layer */ + x1 = leftRotate1_64(b1); + x2 = leftRotate8_64(b2); + x3 = leftRotate25_64(b3); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); +#endif +} + +void knot256_permute_6(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc6, rounds); +} + +void knot256_permute_7(knot256_state_t *state, uint8_t rounds) +{ + knot256_permute(state, rc7, rounds); +} + +void knot384_permute_7(knot384_state_t *state, uint8_t rounds) +{ + const uint8_t *rc = rc7; + uint64_t b2, b4, b6; + uint32_t b3, b5, b7; + + /* Load the input state into local variables; each row is 96 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint32_t x1 = state->W[2]; + uint64_t x2 = state->W[3] | (((uint64_t)(state->W[4])) << 32); + uint32_t x3 = state->W[5]; + uint64_t x4 = state->S[3]; + uint32_t x5 = state->W[8]; + uint64_t x6 = state->W[9] | (((uint64_t)(state->W[10])) << 32); + uint32_t x7 = state->W[11]; +#else + uint64_t x0 = le_load_word64(state->B); + uint32_t x1 = le_load_word32(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 12); + uint32_t x3 = le_load_word32(state->B + 20); + uint64_t x4 = le_load_word64(state->B + 24); + uint32_t x5 = le_load_word32(state->B + 32); + uint64_t x6 = le_load_word64(state->B + 36); + uint32_t x7 = le_load_word32(state->B + 44); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox32(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotateShort_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (32 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + #define leftRotateLong_96(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | \ + (((uint64_t)(b1)) << ((bits) - 32)) | \ + ((b0) >> (96 - (bits))); \ + (a1) = (uint32_t)(((b0) << ((bits) - 32)) >> 32); \ + } while (0) + leftRotateShort_96(x2, x3, b2, b3, 1); + leftRotateShort_96(x4, x5, b4, b5, 8); + leftRotateLong_96(x6, x7, b6, b7, 55); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->W[2] = x1; + state->W[3] = (uint32_t)x2; + state->W[4] = (uint32_t)(x2 >> 32); + state->W[5] = x3; + state->S[3] = x4; + state->W[8] = x5; + state->W[9] = (uint32_t)x6; + state->W[10] = (uint32_t)(x6 >> 32); + state->W[11] = x7; +#else + le_store_word64(state->B, x0); + le_store_word32(state->B + 8, x1); + le_store_word64(state->B + 12, x2); + le_store_word32(state->B + 20, x3); + le_store_word64(state->B + 24, x4); + le_store_word32(state->B + 32, x5); + le_store_word64(state->B + 36, x6); + le_store_word32(state->B + 44, x7); +#endif +} + +static void knot512_permute + (knot512_state_t *state, const uint8_t *rc, uint8_t rounds) +{ + uint64_t b2, b3, b4, b5, b6, b7; + + /* Load the input state into local variables; each row is 128 bits */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + uint64_t x0 = state->S[0]; + uint64_t x1 = state->S[1]; + uint64_t x2 = state->S[2]; + uint64_t x3 = state->S[3]; + uint64_t x4 = state->S[4]; + uint64_t x5 = state->S[5]; + uint64_t x6 = state->S[6]; + uint64_t x7 = state->S[7]; +#else + uint64_t x0 = le_load_word64(state->B); + uint64_t x1 = le_load_word64(state->B + 8); + uint64_t x2 = le_load_word64(state->B + 16); + uint64_t x3 = le_load_word64(state->B + 24); + uint64_t x4 = le_load_word64(state->B + 32); + uint64_t x5 = le_load_word64(state->B + 40); + uint64_t x6 = le_load_word64(state->B + 48); + uint64_t x7 = le_load_word64(state->B + 56); +#endif + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds) { + /* Add the next round constant to the state */ + x0 ^= *rc++; + + /* Substitution layer */ + knot_sbox64(x0, x2, x4, x6, b2, b4, b6); + knot_sbox64(x1, x3, x5, x7, b3, b5, b7); + + /* Linear diffusion layer */ + #define leftRotate_128(a0, a1, b0, b1, bits) \ + do { \ + (a0) = ((b0) << (bits)) | ((b1) >> (64 - (bits))); \ + (a1) = ((b1) << (bits)) | ((b0) >> (64 - (bits))); \ + } while (0) + leftRotate_128(x2, x3, b2, b3, 1); + leftRotate_128(x4, x5, b4, b5, 16); + leftRotate_128(x6, x7, b6, b7, 25); + } + + /* Store the local variables to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0] = x0; + state->S[1] = x1; + state->S[2] = x2; + state->S[3] = x3; + state->S[4] = x4; + state->S[5] = x5; + state->S[6] = x6; + state->S[7] = x7; +#else + le_store_word64(state->B, x0); + le_store_word64(state->B + 8, x1); + le_store_word64(state->B + 16, x2); + le_store_word64(state->B + 24, x3); + le_store_word64(state->B + 32, x4); + le_store_word64(state->B + 40, x5); + le_store_word64(state->B + 48, x6); + le_store_word64(state->B + 56, x7); +#endif +} + +void knot512_permute_7(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc7, rounds); +} + +void knot512_permute_8(knot512_state_t *state, uint8_t rounds) +{ + knot512_permute(state, rc8, rounds); +} diff --git a/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.h b/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.h new file mode 100644 index 0000000..88a782c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/internal-knot.h @@ -0,0 +1,130 @@ +/* + * 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_KNOT_H +#define LW_INTERNAL_KNOT_H + +#include "internal-util.h" + +/** + * \file internal-knot.h + * \brief Permutations that are used by the KNOT AEAD and hash algorithms. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal state of the KNOT-256 permutation. + */ +typedef union +{ + uint64_t S[4]; /**< Words of the state */ + uint8_t B[32]; /**< Bytes of the state */ + +} knot256_state_t; + +/** + * \brief Internal state of the KNOT-384 permutation. + */ +typedef union +{ + uint64_t S[6]; /**< 64-bit words of the state */ + uint32_t W[12]; /**< 32-bit words of the state */ + uint8_t B[48]; /**< Bytes of the state */ + +} knot384_state_t; + +/** + * \brief Internal state of the KNOT-512 permutation. + */ +typedef union +{ + uint64_t S[8]; /**< Words of the state */ + uint8_t B[64]; /**< Bytes of the state */ + +} knot512_state_t; + +/** + * \brief Permutes the KNOT-256 state, using 6-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 52. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_6(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-256 state, using 7-bit round constants. + * + * \param state The KNOT-256 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot256_permute_7(knot256_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-384 state, using 7-bit round constants. + * + * \param state The KNOT-384 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot384_permute_7(knot384_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 7-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 104. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_7(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Permutes the KNOT-512 state, using 8-bit round constants. + * + * \param state The KNOT-512 state to be permuted. + * \param rounds The number of rounds to be performed, 1 to 140. + * + * The input and output \a state will be in little-endian byte order. + */ +void knot512_permute_8(knot512_state_t *state, uint8_t rounds); + +/** + * \brief Generic pointer to a function that performs a KNOT permutation. + * + * \param state Points to the permutation state. + * \param round Number of rounds to perform. + */ +typedef void (*knot_permute_t)(void *state, uint8_t rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/knot/Implementations/crypto_aead/knot256/rhys/internal-util.h b/knot/Implementations/crypto_aead/knot256/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/knot/Implementations/crypto_aead/knot256/rhys/knot-aead.c b/knot/Implementations/crypto_aead/knot256/rhys/knot-aead.c new file mode 100644 index 0000000..5825f01 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/knot-aead.c @@ -0,0 +1,503 @@ +/* + * 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 "knot.h" +#include "internal-knot.h" +#include + +aead_cipher_t const knot_aead_128_256_cipher = { + "KNOT-AEAD-128-256", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_256_encrypt, + knot_aead_128_256_decrypt +}; + +aead_cipher_t const knot_aead_128_384_cipher = { + "KNOT-AEAD-128-384", + KNOT_AEAD_128_KEY_SIZE, + KNOT_AEAD_128_NONCE_SIZE, + KNOT_AEAD_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_128_384_encrypt, + knot_aead_128_384_decrypt +}; + +aead_cipher_t const knot_aead_192_384_cipher = { + "KNOT-AEAD-192-384", + KNOT_AEAD_192_KEY_SIZE, + KNOT_AEAD_192_NONCE_SIZE, + KNOT_AEAD_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_192_384_encrypt, + knot_aead_192_384_decrypt +}; + +aead_cipher_t const knot_aead_256_512_cipher = { + "KNOT-AEAD-256-512", + KNOT_AEAD_256_KEY_SIZE, + KNOT_AEAD_256_NONCE_SIZE, + KNOT_AEAD_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + knot_aead_256_512_encrypt, + knot_aead_256_512_decrypt +}; + +/** + * \brief Rate for KNOT-AEAD-128-256. + */ +#define KNOT_AEAD_128_256_RATE 8 + +/** + * \brief Rate for KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_384_RATE 24 + +/** + * \brief Rate for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_384_RATE 12 + +/** + * \brief Rate for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_512_RATE 16 + +/** + * \brief Absorbs the associated data into a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be at least 1. + */ +static void knot_aead_absorb_ad + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= rate) { + lw_xor_block((unsigned char *)state, ad, rate); + permute(state, rounds); + ad += rate; + adlen -= rate; + } + rate = (unsigned)adlen; + lw_xor_block((unsigned char *)state, ad, rate); + ((unsigned char *)state)[rate] ^= 0x01; + permute(state, rounds); +} + +/** + * \brief Encrypts plaintext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param c Buffer to receive the ciphertext. + * \param m Buffer containing the plaintext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_encrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *c, const unsigned char *m, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_2_dest(c, (unsigned char *)state, m, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +/** + * \brief Decrypts ciphertext data with a KNOT permutation state. + * + * \param state Points to the KNOT permutation state. + * \param permute Points to the function to perform the KNOT permutation. + * \param rounds Number of rounds to perform. + * \param rate Rate of absorption to use with the permutation. + * \param m Buffer to receive the plaintext. + * \param c Buffer containing the ciphertext. + * \param len Length of the plaintext data, must be at least 1. + */ +static void knot_aead_decrypt + (void *state, knot_permute_t permute, uint8_t rounds, unsigned rate, + unsigned char *m, const unsigned char *c, unsigned long long len) +{ + while (len >= rate) { + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + permute(state, rounds); + c += rate; + m += rate; + len -= rate; + } + rate = (unsigned)len; + lw_xor_block_swap(m, (unsigned char *)state, c, rate); + ((unsigned char *)state)[rate] ^= 0x01; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot256_permute_6(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_256_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) +{ + knot256_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + knot256_permute_6(&state, 52); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot256_permute_6, + 28, KNOT_AEAD_128_256_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot256_permute_6(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 32); + memcpy(c + mlen, state.B, KNOT_AEAD_128_TAG_SIZE); + return 0; +} + +int knot_aead_128_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_128_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_128_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_128_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_128_NONCE_SIZE, k, KNOT_AEAD_128_KEY_SIZE); + memset(state.B + KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE, + 0, 47 - (KNOT_AEAD_128_NONCE_SIZE + KNOT_AEAD_128_KEY_SIZE)); + state.B[47] = 0x80; + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_128_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 28, KNOT_AEAD_128_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 32); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_128_TAG_SIZE); +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot384_permute_7(&state, 44); + memcpy(c + mlen, state.B, KNOT_AEAD_192_TAG_SIZE); + return 0; +} + +int knot_aead_192_384_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) +{ + knot384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_192_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_192_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_192_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_192_NONCE_SIZE, k, KNOT_AEAD_192_KEY_SIZE); + knot384_permute_7(&state, 76); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_192_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot384_permute_7, + 40, KNOT_AEAD_192_384_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot384_permute_7(&state, 44); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_192_TAG_SIZE); +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Encrypts the plaintext to produce the ciphertext */ + if (mlen > 0) { + knot_aead_encrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, c, m, mlen); + } + + /* Compute the authentication tag */ + knot512_permute_7(&state, 56); + memcpy(c + mlen, state.B, KNOT_AEAD_256_TAG_SIZE); + return 0; +} + +int knot_aead_256_512_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) +{ + knot512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < KNOT_AEAD_256_TAG_SIZE) + return -1; + *mlen = clen - KNOT_AEAD_256_TAG_SIZE; + + /* Initialize the permutation state to the nonce and the key */ + memcpy(state.B, npub, KNOT_AEAD_256_NONCE_SIZE); + memcpy(state.B + KNOT_AEAD_256_NONCE_SIZE, k, KNOT_AEAD_256_KEY_SIZE); + knot512_permute_7(&state, 100); + + /* Absorb the associated data */ + if (adlen > 0) { + knot_aead_absorb_ad + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, ad, adlen); + } + state.B[sizeof(state.B) - 1] ^= 0x80; /* Domain separation */ + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= KNOT_AEAD_256_TAG_SIZE; + if (clen > 0) { + knot_aead_decrypt + (&state, (knot_permute_t)knot512_permute_7, + 52, KNOT_AEAD_256_512_RATE, m, c, clen); + } + + /* Check the authentication tag */ + knot512_permute_7(&state, 56); + return aead_check_tag + (m, clen, state.B, c + clen, KNOT_AEAD_256_TAG_SIZE); +} diff --git a/knot/Implementations/crypto_aead/knot256/rhys/knot.h b/knot/Implementations/crypto_aead/knot256/rhys/knot.h new file mode 100644 index 0000000..e2c5198 --- /dev/null +++ b/knot/Implementations/crypto_aead/knot256/rhys/knot.h @@ -0,0 +1,459 @@ +/* + * 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_KNOT_H +#define LWCRYPTO_KNOT_H + +#include "aead-common.h" + +/** + * \file knot.h + * \brief KNOT authenticated encryption and hash algorithms. + * + * KNOT is a family of authenticated encryption and hash algorithms built + * around a permutation and the MonkeyDuplex sponge construction. The + * family members are: + * + * \li KNOT-AEAD-128-256 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 256-bit permutation. This is the primary + * encryption member of the family. + * \li KNOT-AEAD-128-384 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-192-384 with a 192-bit key, a 192-bit nonce, and a + * 192-bit tag, built around a 384-bit permutation. + * \li KNOT-AEAD-256-512 with a 256-bit key, a 256-bit nonce, and a + * 256-bit tag, built around a 512-bit permutation. + * \li KNOT-HASH-256-256 with a 256-bit hash output, built around a + * 256-bit permutation. This is the primary hashing member of the family. + * \li KNOT-HASH-256-384 with a 256-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-384-384 with a 384-bit hash output, built around a + * 384-bit permutation. + * \li KNOT-HASH-512-512 with a 512-bit hash output, built around a + * 512-bit permutation. + * + * References: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/knot-spec-round.pdf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-128-256 and + * KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-192-384. + */ +#define KNOT_AEAD_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for KNOT-AEAD-256-512. + */ +#define KNOT_AEAD_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for KNOT-AEAD-128-256 and KNOT-AEAD-128-384. + */ +#define KNOT_AEAD_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-256-256 and KNOT-HASH-256-384. + */ +#define KNOT_HASH_256_SIZE 32 + +/** + * \brief Size of the hash for KNOT-HASH-384-384. + */ +#define KNOT_HASH_384_SIZE 48 + +/** + * \brief Size of the hash for KNOT-HASH-512-512. + */ +#define KNOT_HASH_512_SIZE 64 + +/** + * \brief Meta-information block for the KNOT-AEAD-128-256 cipher. + */ +extern aead_cipher_t const knot_aead_128_256_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-128-384 cipher. + */ +extern aead_cipher_t const knot_aead_128_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-192-384 cipher. + */ +extern aead_cipher_t const knot_aead_192_384_cipher; + +/** + * \brief Meta-information block for the KNOT-AEAD-256-512 cipher. + */ +extern aead_cipher_t const knot_aead_256_512_cipher; + +/** + * \brief Meta-information block for the KNOT-HASH-256-256 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_256_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-256-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_256_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-384-384 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_384_384_algorithm; + +/** + * \brief Meta-information block for the KNOT-HASH-512-512 algorithm. + */ +extern aead_hash_algorithm_t const knot_hash_512_512_algorithm; + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_256_decrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_256_encrypt() + */ +int knot_aead_128_256_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_128_384_decrypt() + */ +int knot_aead_128_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-128-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_128_384_encrypt() + */ +int knot_aead_128_384_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); + + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_192_384_decrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-192-384. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_192_384_encrypt() + */ +int knot_aead_192_384_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); + +/** + * \brief Encrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa knot_aead_256_512_decrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Decrypts and authenticates a packet with KNOT-AEAD-256-512. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa knot_aead_256_512_encrypt() + */ +int knot_aead_256_512_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); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-256. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_256 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-256-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_256_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 knot_hash_256_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-384-384. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_384_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 knot_hash_384_384 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Hashes a block of input data with KNOT-HASH-512-512. + * + * \param out Buffer to receive the hash output which must be at least + * KNOT_HASH_512_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 knot_hash_512_512 + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.c b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.h b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/api.h b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/api.h new file mode 100644 index 0000000..4bf8f5c --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/encrypt.c b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/encrypt.c new file mode 100644 index 0000000..1573370 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "lotus-locus.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 locus_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 locus_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.c b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.c new file mode 100644 index 0000000..321d079 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.c @@ -0,0 +1,745 @@ +/* + * 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 "internal-gift64.h" +#include "internal-util.h" +#include + +/* Round constants for GIFT-64 in the fixsliced representation */ +static uint32_t const GIFT64_RC[28] = { + 0x22000011, 0x00002299, 0x11118811, 0x880000ff, 0x33111199, 0x990022ee, + 0x22119933, 0x880033bb, 0x22119999, 0x880022ff, 0x11119922, 0x880033cc, + 0x33008899, 0x99002299, 0x33118811, 0x880000ee, 0x33110099, 0x990022aa, + 0x22118833, 0x880022bb, 0x22111188, 0x88002266, 0x00009922, 0x88003300, + 0x22008811, 0x00002288, 0x00118811, 0x880000bb +}; + +int gift64b_init + (gift64b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + ks->k[0] = be_load_word32(key); + ks->k[1] = be_load_word32(key + 4); + ks->k[2] = be_load_word32(key + 8); + ks->k[3] = be_load_word32(key + 12); + gift64b_update_round_keys(ks); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift64b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t t = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= t; \ + (a) ^= t << (shift); \ + } while (0) + +/** + * \brief Performs the GIFT-64 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift64b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-64 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift64b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/* Rotates a state word left by 1 position in the fixsliced representation: + * + * 0 1 2 3 1 2 3 0 + * 4 5 6 7 ==> 5 6 7 4 + * 8 9 10 11 9 10 11 8 + * 12 13 14 15 13 14 14 12 + */ +#define gift64b_rotate_left_1(x) \ + ((((x) >> 1) & 0x77777777U) | (((x) & 0x11111111U) << 3)) + +/* Rotates a state word left by 2 positions in the fixsliced representation: + * + * 0 1 2 3 2 3 0 1 + * 4 5 6 7 ==> 6 7 4 5 + * 8 9 10 11 10 11 8 9 + * 12 13 14 15 14 15 12 13 + */ +#define gift64b_rotate_left_2(x) \ + ((((x) >> 2) & 0x33333333U) | (((x) & 0x33333333U) << 2)) + +/* Rotates a state word left by 3 positions in the fixsliced representation: + * + * 0 1 2 3 3 0 1 2 + * 4 5 6 7 ==> 7 4 5 6 + * 8 9 10 11 11 8 9 10 + * 12 13 14 15 15 12 13 14 + */ +#define gift64b_rotate_left_3(x) \ + ((((x) >> 3) & 0x11111111U) | (((x) & 0x77777777U) << 1)) + +/* Rotates a state word right by 1 position in the fixsliced representation */ +#define gift64b_rotate_right_1(x) gift64b_rotate_left_3(x) + +/* Rotates a state word right by 2 positions in the fixsliced representation */ +#define gift64b_rotate_right_2(x) gift64b_rotate_left_2(x) + +/* Rotates a state word right by 3 positions in the fixsliced representation */ +#define gift64b_rotate_right_3(x) gift64b_rotate_left_1(x) + +/* Rotates a state word up by 1 position in the fixsliced representation: + * + * 0 1 2 3 4 5 6 7 + * 4 5 6 7 ==> 8 9 10 11 + * 8 9 10 11 12 13 14 15 + * 12 13 14 15 0 1 2 3 + */ +#define gift64b_rotate_up_1(x) (rightRotate8((x))) + +/* Rotates a state word up by 2 positions in the fixsliced representation: + * + * 0 1 2 3 8 9 10 11 + * 4 5 6 7 ==> 12 13 14 15 + * 8 9 10 11 0 1 2 3 + * 12 13 14 15 4 5 6 7 + */ +#define gift64b_rotate_up_2(x) (rightRotate16((x))) + +/* Rotates a state word up by 3 positions in the fixsliced representation: + * + * 0 1 2 3 12 13 14 15 + * 4 5 6 7 ==> 0 1 2 3 + * 8 9 10 11 4 5 6 7 + * 12 13 14 15 8 9 10 11 + */ +#define gift64b_rotate_up_3(x) (rightRotate24((x))) + +/* Rotates a state word down by 1 position in the fixsliced representation */ +#define gift64b_rotate_down_1(x) gift64b_rotate_up_3(x) + +/* Rotates a state word down by 2 positions in the fixsliced representation */ +#define gift64b_rotate_down_2(x) gift64b_rotate_up_2(x) + +/* Rotates a state word down by 3 positions in the fixsliced representation */ +#define gift64b_rotate_down_3(x) gift64b_rotate_up_1(x) + +/* Permutation code to rearrange key bits into fixsliced form. Permutations + * generated wth "http://programming.sirrida.de/calcperm.php" */ +#define gift64b_rearrange1_transpose_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 8 16 24 3 11 19 27 2 10 18 26 1 9 17 25 * */ \ + bit_permute_step(out, 0x0000CCCCU, 16); \ + bit_permute_step(out, 0x30030330U, 2); \ + bit_permute_step(out, 0x00960096U, 8); \ + bit_permute_step(out, 0x05500550U, 1); \ + bit_permute_step(out, 0x0A0A0A0AU, 4); \ + } while (0) +#define gift64b_rearrange1_transpose_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 8 16 24 3 11 19 27 2 10 18 26 1 9 17 25 * */ \ + bit_permute_step(out, 0x0000CCCCU, 16); \ + bit_permute_step(out, 0x30030330U, 2); \ + bit_permute_step(out, 0x00960096U, 8); \ + bit_permute_step(out, 0x05500550U, 1); \ + bit_permute_step(out, 0x0A0A0A0AU, 4); \ + } while (0) +#define gift64b_rearrange1_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 1 2 3 24 25 26 27 16 17 18 19 8 9 10 11 * */ \ + out = (out & 0x0000000FU) | ((out & 0x00000F00U) << 8) | \ + ((out & 0x000000F0U) << 20) | ((out & 0x0000F000U) >> 4); \ + } while (0) +#define gift64b_rearrange1_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 1 2 3 24 25 26 27 16 17 18 19 8 9 10 11 * */ \ + out = (out & 0x0000000FU) | ((out & 0x00000F00U) << 8) | \ + ((out & 0x000000F0U) << 20) | ((out & 0x0000F000U) >> 4); \ + } while (0) +#define gift64b_rearrange2_transpose_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 * */ \ + bit_permute_step(out, 0x0A0A0A0AU, 3); \ + bit_permute_step(out, 0x00CC00CCU, 6); \ + bit_permute_step(out, 0x0000F0F0U, 12); \ + bit_permute_step(out, 0x0000FF00U, 8); \ + } while (0) +#define gift64b_rearrange2_transpose_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 * */ \ + bit_permute_step(out, 0x0A0A0A0AU, 3); \ + bit_permute_step(out, 0x00CC00CCU, 6); \ + bit_permute_step(out, 0x0000F0F0U, 12); \ + bit_permute_step(out, 0x0000FF00U, 8); \ + } while (0) +#define gift64b_rearrange2_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 * */ \ + out = (out & 0x0000000FU) | ((out & 0x000000F0U) << 4) | \ + ((out & 0x00000F00U) << 8) | ((out & 0x0000F000U) << 12); \ + } while (0) +#define gift64b_rearrange2_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 * */ \ + out = (out & 0x0000000FU) | ((out & 0x000000F0U) << 4) | \ + ((out & 0x00000F00U) << 8) | ((out & 0x0000F000U) << 12); \ + } while (0) + +void gift64b_update_round_keys(gift64b_key_schedule_t *ks) +{ + uint32_t x; + + /* First round */ + gift64b_rearrange1_transpose_low(x, ks->k[3]); + ks->rk[0] = ~(x | (x << 4)); + gift64b_rearrange1_transpose_high(x, ks->k[3]); + ks->rk[1] = x | (x << 4); + + /* Second round */ + gift64b_rearrange1_low(x, ks->k[2]); + x = x | (x << 4); + gift64b_swap_move(x, x, 0x22222222U, 2); + ks->rk[2] = ~x; + gift64b_rearrange1_high(x, ks->k[2]); + x = x | (x << 4); + gift64b_swap_move(x, x, 0x22222222U, 2); + ks->rk[3] = x; + + /* Third round */ + gift64b_rearrange2_transpose_low(x, ks->k[1]); + gift64b_swap_move(x, x, 0x00000F00U, 16); + ks->rk[4] = ~(x | (x << 4)); + gift64b_rearrange2_transpose_high(x, ks->k[1]); + gift64b_swap_move(x, x, 0x00000F00U, 16); + ks->rk[5] = x | (x << 4); + + /* Fourth round */ + gift64b_rearrange2_low(x, ks->k[0]); + ks->rk[6] = ~(x | (x << 4)); + gift64b_rearrange2_high(x, ks->k[0]); + ks->rk[7] = x | (x << 4); +} + +/** + * \brief Perform the core of GIFT-64 encryption on two blocks in parallel. + * + * \param ks Points to the key schedule to use to encrypt the blocks. + * \param state Buffer containing the two blocks in bit-sliced form, + * on input and output. + * \param Tweak value or zero if there is no tweak. + */ +static void gift64b_encrypt_core + (const gift64b_key_schedule_t *ks, uint32_t state[4], uint32_t tweak) +{ + const uint32_t *rc = GIFT64_RC; + uint32_t s0, s1, s2, s3, temp; + uint32_t rk[8]; + uint8_t round; + + /* Start with the pre-computed round keys for the first four rounds */ + memcpy(rk, ks->rk, sizeof(ks->rk)); + + /* Load the state into local variables */ + s0 = state[0]; + s1 = state[1]; + s2 = state[2]; + s3 = state[3]; + + /* Perform all 28 rounds four at a time. We use the "fixslicing" method. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of four rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 4 rounds. + */ + for (round = 0; round < 28; round += 4, rc += 4) { + /* 1st round - S-box, rotate left, add round key */ + gift64b_sbox(s0, s1, s2, s3); + s1 = gift64b_rotate_left_1(s1); + s2 = gift64b_rotate_left_2(s2); + s0 = gift64b_rotate_left_3(s0); + s3 ^= rk[0]; + s1 ^= rk[1]; + s0 ^= rc[0]; + + /* 2nd round - S-box, rotate up, add round key (s0 and s3 swapped) */ + gift64b_sbox(s3, s1, s2, s0); + s1 = gift64b_rotate_up_1(s1); + s2 = gift64b_rotate_up_2(s2); + s3 = gift64b_rotate_up_3(s3); + s0 ^= rk[2]; + s1 ^= rk[3]; + s3 ^= rc[1]; + + /* 3rd round - S-box, rotate right, add round key */ + gift64b_sbox(s0, s1, s2, s3); + s1 = gift64b_rotate_right_1(s1); + s2 = gift64b_rotate_right_2(s2); + s0 = gift64b_rotate_right_3(s0); + s3 ^= rk[4]; + s1 ^= rk[5]; + s0 ^= rc[2]; + + /* 4th round - S-box, rotate down, add round key (s0 and s3 swapped) */ + gift64b_sbox(s3, s1, s2, s0); + s1 = gift64b_rotate_down_1(s1); + s2 = gift64b_rotate_down_2(s2); + s3 = gift64b_rotate_down_3(s3); + s0 ^= rk[6]; + s1 ^= rk[7]; + s3 ^= rc[3]; + + /* Add the tweak every four encryption rounds except the last */ + if (round < 24) + s2 ^= tweak; + + /* Derive the round keys for the next 4 rounds */ + rk[0] = gift64b_rotate_left_1(rk[0]); + rk[1] = (gift64b_rotate_left_3(rk[1]) << 16) | (rk[1] >> 16); + rk[2] = rightRotate8(rk[2]); + temp = gift64b_rotate_left_2(rk[3]); + rk[3] = (temp & 0x99999999U) | leftRotate8(temp & 0x66666666U); + rk[4] = gift64b_rotate_left_3(rk[4]); + temp = rightRotate16(rk[5]); + rk[5] = (gift64b_rotate_left_1(temp) & 0x00FFFF00U) | + (temp & 0xFF0000FFU); + rk[6] = leftRotate8(rk[6]); + temp = gift64b_rotate_left_2(rk[7]); + rk[7] = (temp & 0x33333333U) | rightRotate8(temp & 0xCCCCCCCCU); + } + + /* Copy the local variables to the output state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} + +/** + * \brief Perform the core of GIFT-64 decryption on two blocks in parallel. + * + * \param ks Points to the key schedule to use to encrypt the blocks. + * \param state Buffer containing the two blocks in bit-sliced form, + * on input and output. + * \param Tweak value or zero if there is no tweak. + */ +static void gift64b_decrypt_core + (const gift64b_key_schedule_t *ks, uint32_t state[4], uint32_t tweak) +{ + const uint32_t *rc = GIFT64_RC + 28 - 4; + uint32_t s0, s1, s2, s3, temp; + uint32_t rk[8]; + uint8_t round; + + /* Start with the pre-computed round keys for the first four rounds */ + memcpy(rk, ks->rk, sizeof(ks->rk)); + + /* Fast forward the key schedule to the end by permuting each round + * key by the amount it would see under the full set of rounds. + * Generated with "http://programming.sirrida.de/calcperm.php" */ + /* P0: 1 2 3 0 5 6 7 4 9 10 11 8 13 14 15 12 17 18 + * 19 16 21 22 23 20 25 26 27 24 29 30 31 28 */ + rk[0] = ((rk[0] & 0x77777777U) << 1) | ((rk[0] & 0x88888888U) >> 3); + /* P1: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + * 31 3 0 1 2 7 4 5 6 11 8 9 10 15 12 13 14 */ + rk[1] = ((rk[1] & 0xEEEE0000U) >> 17) | ((rk[1] & 0x0000FFFFU) << 16) | + ((rk[1] & 0x11110000U) >> 13); + /* P2: 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + * 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 */ + rk[2] = leftRotate8(rk[2]); + /* P3: 2 27 24 1 6 31 28 5 10 3 0 9 14 7 4 13 18 11 + * 8 17 22 15 12 21 26 19 16 25 30 23 20 29 */ + rk[3] = ((rk[3] & 0x11111111U) << 2) | leftRotate22(rk[3] & 0x44444444U) | + leftRotate26(rk[3] & 0x22222222U) | ((rk[3] & 0x88888888U) >> 2); + /* P4: 3 0 1 2 7 4 5 6 11 8 9 10 15 12 13 14 19 16 + * 17 18 23 20 21 22 27 24 25 26 31 28 29 30 */ + rk[4] = ((rk[4] & 0x11111111U) << 3) | ((rk[4] & 0xEEEEEEEEU) >> 1); + /* P5: 16 17 18 19 20 21 22 23 25 26 27 24 29 30 31 + * 28 1 2 3 0 5 6 7 4 8 9 10 11 12 13 14 15 */ + rk[5] = leftRotate13(rk[5] & 0x00888800U) | + leftRotate16(rk[5] & 0xFF0000FFU) | + leftRotate17(rk[5] & 0x00777700U); + /* P6: 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 8 9 10 + * 11 12 13 14 15 16 17 18 19 20 21 22 23 */ + rk[6] = leftRotate24(rk[6]); + /* P7: 2 3 8 9 6 7 12 13 10 11 16 17 14 15 20 21 18 19 + * 24 25 22 23 28 29 26 27 0 1 30 31 4 5 */ + rk[7] = ((rk[7] & 0x33333333U) << 2) | leftRotate6(rk[7] & 0xCCCCCCCCU); + + /* Load the state into local variables */ + s0 = state[0]; + s1 = state[1]; + s2 = state[2]; + s3 = state[3]; + + /* Perform all 28 rounds four at a time. We use the "fixslicing" method. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of four rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 4 rounds. + */ + for (round = 0; round < 28; round += 4, rc -= 4) { + /* Derive the round keys for the previous 4 rounds */ + rk[0] = gift64b_rotate_right_1(rk[0]); + temp = rk[1] >> 16; + rk[1] = gift64b_rotate_right_3(temp) | (rk[1] << 16); + rk[2] = leftRotate8(rk[2]); + temp = (rk[3] & 0x99999999U) | rightRotate8(rk[3] & 0x66666666U); + rk[3] = gift64b_rotate_right_2(temp); + rk[4] = gift64b_rotate_right_3(rk[4]); + temp = (gift64b_rotate_right_1(rk[5]) & 0x00FFFF00U) | + (rk[5] & 0xFF0000FFU); + rk[5] = leftRotate16(temp); + rk[6] = rightRotate8(rk[6]); + temp = (rk[7] & 0x33333333U) | leftRotate8(rk[7] & 0xCCCCCCCCU); + rk[7] = gift64b_rotate_right_2(temp); + + /* Add the tweak every four decryption rounds except the first */ + if (round != 0) + s2 ^= tweak; + + /* 4th round - S-box, rotate down, add round key (s0 and s3 swapped) */ + s0 ^= rk[6]; + s1 ^= rk[7]; + s3 ^= rc[3]; + s1 = gift64b_rotate_up_1(s1); + s2 = gift64b_rotate_up_2(s2); + s3 = gift64b_rotate_up_3(s3); + gift64b_inv_sbox(s0, s1, s2, s3); + + /* 3rd round - S-box, rotate right, add round key */ + s3 ^= rk[4]; + s1 ^= rk[5]; + s0 ^= rc[2]; + s1 = gift64b_rotate_left_1(s1); + s2 = gift64b_rotate_left_2(s2); + s0 = gift64b_rotate_left_3(s0); + gift64b_inv_sbox(s3, s1, s2, s0); + + /* 2nd round - S-box, rotate up, add round key (s0 and s3 swapped) */ + s0 ^= rk[2]; + s1 ^= rk[3]; + s3 ^= rc[1]; + s1 = gift64b_rotate_down_1(s1); + s2 = gift64b_rotate_down_2(s2); + s3 = gift64b_rotate_down_3(s3); + gift64b_inv_sbox(s0, s1, s2, s3); + + /* 1st round - S-box, rotate left, add round key */ + s3 ^= rk[0]; + s1 ^= rk[1]; + s0 ^= rc[0]; + s1 = gift64b_rotate_right_1(s1); + s2 = gift64b_rotate_right_2(s2); + s0 = gift64b_rotate_right_3(s0); + gift64b_inv_sbox(s3, s1, s2, s0); + } + + /* Copy the local variables to the output state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} + +int gift64n_init + (gift64n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian byte order from the LOTUS-AEAD submission */ + if (!ks || !key || key_len != 16) + return 0; + ks->k[0] = le_load_word32(key + 12); + ks->k[1] = le_load_word32(key + 8); + ks->k[2] = le_load_word32(key + 4); + ks->k[3] = le_load_word32(key); + gift64b_update_round_keys(ks); + return 1; +} + +/** + * \brief Converts the GIFT-64 nibble-based representation into word-based + * (littlen-endian version). + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The output words will be in fixsliced form. Technically the output will + * contain two blocks for gift64b_encrypt_core() to process in parallel but + * both blocks will have the same value. + */ +static void gift64n_to_words(uint32_t output[4], const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input block into 32-bit words */ + s0 = le_load_word32(input); + s2 = le_load_word32(input + 4); + + /* Rearrange the bits in the block */ + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + + /* Split into two identical blocks in fixsliced form */ + s1 = s0; + s3 = s2; + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +/** + * \brief Converts the GIFT-64 word-based representation into nibble-based + * (little-endian version). + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + * + * The input words are in fixsliced form. Technically there are two + * identical blocks in the input. We drop one when we write to the output. + */ +static void gift64n_to_nibbles(unsigned char *output, const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Load the state and split the two blocks into separate words */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + + /* Rearrange the bits in the first block back into nibble form */ + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + le_store_word32(output, s0); + le_store_word32(output + 4, s2); +} + +void gift64n_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_encrypt_core(ks, state, 0); + gift64n_to_nibbles(output, state); +} + +void gift64n_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_decrypt_core(ks, state, 0); + gift64n_to_nibbles(output, state); +} + +/** + * \brief Converts the GIFT-64 nibble-based representation into word-based + * (big-endian version). + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The output words will be in fixsliced form. Technically the output will + * contain two blocks for gift64b_encrypt_core() to process in parallel but + * both blocks will have the same value. + */ +static void gift64nb_to_words(uint32_t output[4], const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input block into 32-bit words */ + s0 = be_load_word32(input + 4); + s2 = be_load_word32(input); + + /* Rearrange the bits in the block */ + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + + /* Split into two identical blocks in fixsliced form */ + s1 = s0; + s3 = s2; + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +/** + * \brief Converts the GIFT-64 word-based representation into nibble-based + * (big-endian version). + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + * + * The input words are in fixsliced form. Technically there are two + * identical blocks in the input. We drop one when we write to the output. + */ +static void gift64nb_to_nibbles(unsigned char *output, const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Load the state and split the two blocks into separate words */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + + /* Rearrange the bits in the first block back into nibble form */ + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + be_store_word32(output, s2); + be_store_word32(output + 4, s0); +} + +void gift64nb_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64nb_to_words(state, input); + gift64b_encrypt_core(ks, state, 0); + gift64nb_to_nibbles(output, state); +} + +void gift64nb_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64nb_to_words(state, input); + gift64b_decrypt_core(ks, state, 0); + gift64nb_to_nibbles(output, state); +} + +/* 4-bit tweak values expanded to 32-bit in fixsliced form */ +static uint32_t const GIFT64_tweaks[16] = { + 0x00000000, 0xee11ee11, 0xdd22dd22, 0x33333333, 0xbb44bb44, 0x55555555, + 0x66666666, 0x88778877, 0x77887788, 0x99999999, 0xaaaaaaaa, 0x44bb44bb, + 0xcccccccc, 0x22dd22dd, 0x11ee11ee, 0xffffffff +}; + +void gift64t_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_encrypt_core(ks, state, GIFT64_tweaks[tweak]); + gift64n_to_nibbles(output, state); +} + +void gift64t_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_decrypt_core(ks, state, GIFT64_tweaks[tweak]); + gift64n_to_nibbles(output, state); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.h b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.h new file mode 100644 index 0000000..40479c7 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-gift64.h @@ -0,0 +1,194 @@ +/* + * 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_GIFT64_H +#define LW_INTERNAL_GIFT64_H + +/** + * \file internal-gift64.h + * \brief GIFT-64 block cipher. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-64 block in bytes. + */ +#define GIFT64_BLOCK_SIZE 8 + +/** + * \brief Structure of the key schedule for GIFT-64 (bit-sliced). + */ +typedef struct +{ + uint32_t k[4]; /**< Words of the key schedule */ + uint32_t rk[8]; /**< Pre-computed round keys for fixsliced form */ + +} gift64b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-64 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift64b_init + (gift64b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Updates the round keys after a change in the base key. + * + * \param ks Points to the key schedule to update. + */ +void gift64b_update_round_keys(gift64b_key_schedule_t *ks); + +/** + * \brief Structure of the key schedule for GIFT-64 (nibble-based). + */ +typedef gift64b_key_schedule_t gift64n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-64 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift64n_init + (gift64n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 64-bit block with GIFT-64 (nibble-based). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void gift64n_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 64-bit block with GIFT-64 (nibble-based). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + */ +void gift64n_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with GIFT-64 (nibble-based big-endian). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void gift64nb_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 64-bit block with GIFT-64 (nibble-based big-endian). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + */ +void gift64nb_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with TweGIFT-64 (tweakable variant). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * \param tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-64 is used by the LOTUS/LOCUS submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift64n_encrypt(). + */ +void gift64t_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 64-bit block with TweGIFT-64 (tweakable variant). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * \param tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-64 is used by the LOTUS/LOCUS submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift64n_decrypt(). + */ +void gift64t_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-util.h b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.c b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.c new file mode 100644 index 0000000..e60b084 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.c @@ -0,0 +1,436 @@ +/* + * 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 "lotus-locus.h" +#include "internal-gift64.h" +#include "internal-util.h" +#include + +aead_cipher_t const lotus_aead_cipher = { + "LOTUS-AEAD", + LOTUS_AEAD_KEY_SIZE, + LOTUS_AEAD_NONCE_SIZE, + LOTUS_AEAD_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + lotus_aead_encrypt, + lotus_aead_decrypt +}; + +aead_cipher_t const locus_aead_cipher = { + "LOCUS-AEAD", + LOCUS_AEAD_KEY_SIZE, + LOCUS_AEAD_NONCE_SIZE, + LOCUS_AEAD_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + locus_aead_encrypt, + locus_aead_decrypt +}; + +/** + * \brief Multiplies a key by 2 in the GF(128) field. + * + * \param ks The key schedule structure containing the key in host byte order. + */ +STATIC_INLINE void lotus_or_locus_mul_2(gift64n_key_schedule_t *ks) +{ + uint32_t mask = (uint32_t)(((int32_t)(ks->k[0])) >> 31); + ks->k[0] = (ks->k[0] << 1) | (ks->k[1] >> 31); + ks->k[1] = (ks->k[1] << 1) | (ks->k[2] >> 31); + ks->k[2] = (ks->k[2] << 1) | (ks->k[3] >> 31); + ks->k[3] = (ks->k[3] << 1) ^ (mask & 0x87); + gift64b_update_round_keys(ks); +} + +/** + * \brief Initializes a LOTUS-AEAD or LOCUS-AEAD cipher instance. + * + * \param ks Key schedule to initialize. + * \param deltaN Delta-N value for the cipher state. + * \param key Points to the 16-byte key for the cipher instance. + * \param nonce Points to the 16-byte key for the cipher instance. + * \param T Points to a temporary buffer of LOTUS_AEAD_KEY_SIZE bytes + * that will be destroyed during this function. + */ +static void lotus_or_locus_init + (gift64n_key_schedule_t *ks, + unsigned char deltaN[GIFT64_BLOCK_SIZE], + const unsigned char *key, + const unsigned char *nonce, + unsigned char *T) +{ + gift64n_init(ks, key, LOTUS_AEAD_KEY_SIZE); + memset(deltaN, 0, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, deltaN, deltaN, 0); + lw_xor_block_2_src(T, key, nonce, LOTUS_AEAD_KEY_SIZE); + gift64n_init(ks, T, LOTUS_AEAD_KEY_SIZE); + gift64t_encrypt(ks, deltaN, deltaN, 1); +} + +/** + * \brief Processes associated data for LOTUS-AEAD or LOCUS-AEAD. + * + * \param ks Points to the key schedule. + * \param deltaN Points to the Delta-N value from the state. + * \param V Points to the V value from the state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void lotus_or_locus_process_ad + (gift64n_key_schedule_t *ks, + const unsigned char deltaN[GIFT64_BLOCK_SIZE], + unsigned char V[GIFT64_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned char temp; + while (adlen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(ks); + lw_xor_block_2_src(X, ad, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, X, X, 2); + lw_xor_block(V, X, GIFT64_BLOCK_SIZE); + ad += GIFT64_BLOCK_SIZE; + adlen -= GIFT64_BLOCK_SIZE; + } + lotus_or_locus_mul_2(ks); + temp = (unsigned)adlen; + if (temp < GIFT64_BLOCK_SIZE) { + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(X, ad, temp); + X[temp] ^= 0x01; + gift64t_encrypt(ks, X, X, 3); + } else { + lw_xor_block_2_src(X, ad, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, X, X, 2); + } + lw_xor_block(V, X, GIFT64_BLOCK_SIZE); +} + +/** + * \brief Generates the authentication tag for LOTUS-AEAD or LOCUS-AEAD. + * + * \param ks Points to the key schedule. + * \param tag Points to the buffer to receive the authentication tag. + * \param deltaN Points to the Delta-N value from the state. + * \param W Points to the W value from the state. + * \param V Points to the V value from the state. + */ +static void lotus_or_locus_gen_tag + (gift64n_key_schedule_t *ks, unsigned char *tag, + unsigned char deltaN[GIFT64_BLOCK_SIZE], + unsigned char W[GIFT64_BLOCK_SIZE], + unsigned char V[GIFT64_BLOCK_SIZE]) +{ + lotus_or_locus_mul_2(ks); + lw_xor_block(W, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(W, V, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, W, W, 6); + lw_xor_block_2_src(tag, W, deltaN, GIFT64_BLOCK_SIZE); +} + +int lotus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X1[GIFT64_BLOCK_SIZE]; + unsigned char X2[GIFT64_BLOCK_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + LOTUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > (GIFT64_BLOCK_SIZE * 2)) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X1, m, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X1, 4); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block_2_src + (X2, m + GIFT64_BLOCK_SIZE, X2, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(c, X2, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block_2_src + (c + GIFT64_BLOCK_SIZE, X1, X2, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE * 2; + m += GIFT64_BLOCK_SIZE * 2; + mlen -= GIFT64_BLOCK_SIZE * 2; + } + temp = (unsigned)mlen; + lotus_or_locus_mul_2(&ks); + memcpy(X1, deltaN, GIFT64_BLOCK_SIZE); + X1[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X2, X1, 12); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 12); + if (temp <= GIFT64_BLOCK_SIZE) { + lw_xor_block(WV, m, temp); + lw_xor_block(X2, m, temp); + lw_xor_block_2_src(c, X2, deltaN, temp); + } else { + lw_xor_block(X2, m, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(c, X2, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + temp -= GIFT64_BLOCK_SIZE; + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, m, temp); + lw_xor_block(X1, X2, temp); + lw_xor_block_2_src(c, X1, m, temp); + } + c += temp; + } + + /* Generate the authentication tag */ + lotus_or_locus_gen_tag(&ks, c, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return 0; +} + +int lotus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X1[GIFT64_BLOCK_SIZE]; + unsigned char X2[GIFT64_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < LOTUS_AEAD_TAG_SIZE) + return -1; + *mlen = clen - LOTUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= LOTUS_AEAD_TAG_SIZE; + if (clen > 0) { + while (clen > (GIFT64_BLOCK_SIZE * 2)) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X1, c, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X1, 5); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block(X2, c + GIFT64_BLOCK_SIZE, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(m, X2, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block_2_src + (m + GIFT64_BLOCK_SIZE, X1, X2, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE * 2; + m += GIFT64_BLOCK_SIZE * 2; + clen -= GIFT64_BLOCK_SIZE * 2; + } + temp = (unsigned)clen; + lotus_or_locus_mul_2(&ks); + memcpy(X1, deltaN, GIFT64_BLOCK_SIZE); + X1[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X2, X1, 12); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 12); + if (temp <= GIFT64_BLOCK_SIZE) { + lw_xor_block_2_src(m, X2, c, temp); + lw_xor_block(m, deltaN, temp); + lw_xor_block(X2, m, temp); + lw_xor_block(WV, m, temp); + } else { + lw_xor_block_2_src(m, X2, c, GIFT64_BLOCK_SIZE); + lw_xor_block(m, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(X2, m, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + temp -= GIFT64_BLOCK_SIZE; + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(X1, X2, temp); + lw_xor_block_2_src(m, X1, c, temp); + lw_xor_block(WV, m, temp); + } + c += temp; + } + + /* Check the authentication tag */ + lotus_or_locus_gen_tag(&ks, WV, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return aead_check_tag(mtemp, *mlen, WV, c, LOTUS_AEAD_TAG_SIZE); +} + +int locus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + LOCUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X, m, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 4); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 4); + lw_xor_block_2_src(c, X, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + mlen -= GIFT64_BLOCK_SIZE; + } + temp = (unsigned)mlen; + lotus_or_locus_mul_2(&ks); + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + X[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + lw_xor_block(WV, m, temp); + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(X, deltaN, temp); + lw_xor_block_2_src(c, m, X, temp); + c += temp; + } + + /* Generate the authentication tag */ + lotus_or_locus_gen_tag(&ks, c, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return 0; +} + +int locus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < LOCUS_AEAD_TAG_SIZE) + return -1; + *mlen = clen - LOCUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= LOCUS_AEAD_TAG_SIZE; + if (clen > 0) { + while (clen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X, c, deltaN, GIFT64_BLOCK_SIZE); + gift64t_decrypt(&ks, X, X, 4); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_decrypt(&ks, X, X, 4); + lw_xor_block_2_src(m, X, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + clen -= GIFT64_BLOCK_SIZE; + } + temp = (unsigned)clen; + lotus_or_locus_mul_2(&ks); + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + X[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(X, deltaN, temp); + lw_xor_block_2_src(m, c, X, temp); + lw_xor_block(WV, m, temp); + c += temp; + } + + /* Check the authentication tag */ + lotus_or_locus_gen_tag(&ks, WV, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return aead_check_tag(mtemp, *mlen, WV, c, LOCUS_AEAD_TAG_SIZE); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.h b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.h new file mode 100644 index 0000000..85434a8 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64locusaeadv1/rhys/lotus-locus.h @@ -0,0 +1,223 @@ +/* + * 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_LOTUS_LOCUS_H +#define LWCRYPTO_LOTUS_LOCUS_H + +#include "aead-common.h" + +/** + * \file lotus-locus.h + * \brief LOTUS-AEAD and LOCUS-AEAD authenticated encryption algorithms. + * + * LOTUS-AEAD and LOCUS-AEAD are authenticated encryption algorithms + * that are based around a tweakable variant of the GIFT-64 block cipher + * called TweGIFT-64. Both AEAD algorithms have a 128-bit key, a 128-bit + * nonce, and a 64-bit tag. + * + * The two algorithms have the same key initialization, associated data + * processing, and tag generation mechanisms. They differ in how the + * input is encrypted with TweGIFT-64. + * + * LOTUS-AEAD uses a method similar to the block cipher mode OTR. + * TweGIFT-64 is essentially converted into a 128-bit block cipher + * using a Feistel construction and four TweGIFT-64 block operations + * every 16 bytes of input. + * + * LOCUS-AEAD uses a method similar to the block cipher mode OCB + * with two TweGIFT-64 block operations for every 8 bytes of input. + * LOCUS-AEAD requires both the block encrypt and block decrypt + * operations of TweGIFT-64, which increases the overall code size. + * LOTUS-AEAD only needs the block encrypt operation. + * + * LOTUS-AEAD is the primary member of the family. + * + * References: https://www.isical.ac.in/~lightweight/lotus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for LOTUS-AEAD. + */ +#define LOTUS_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for LOTUS-AEAD. + */ +#define LOTUS_AEAD_TAG_SIZE 8 + +/** + * \brief Size of the nonce for LOTUS-AEAD. + */ +#define LOTUS_AEAD_NONCE_SIZE 16 + +/** + * \brief Size of the key for LOCUS-AEAD. + */ +#define LOCUS_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for LOCUS-AEAD. + */ +#define LOCUS_AEAD_TAG_SIZE 8 + +/** + * \brief Size of the nonce for LOCUS-AEAD. + */ +#define LOCUS_AEAD_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the LOTUS-AEAD cipher. + */ +extern aead_cipher_t const lotus_aead_cipher; + +/** + * \brief Meta-information block for the LOCUS-AEAD cipher. + */ +extern aead_cipher_t const locus_aead_cipher; + +/** + * \brief Encrypts and authenticates a packet with LOTUS-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa lotus_aead_decrypt() + */ +int lotus_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); + +/** + * \brief Decrypts and authenticates a packet with LOTUS-AEAD. + * + * \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 - not used by this algorithm. + * \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 9 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa lotus_aead_encrypt() + */ +int lotus_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); + +/** + * \brief Encrypts and authenticates a packet with LOCUS-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa locus_aead_decrypt() + */ +int locus_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); + +/** + * \brief Decrypts and authenticates a packet with LOCUS-AEAD. + * + * \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 - not used by this algorithm. + * \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 9 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa locus_aead_encrypt() + */ +int locus_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.c b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.h b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/api.h b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/api.h new file mode 100644 index 0000000..4bf8f5c --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/encrypt.c b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/encrypt.c new file mode 100644 index 0000000..e089543 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "lotus-locus.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 lotus_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 lotus_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.c b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.c new file mode 100644 index 0000000..321d079 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.c @@ -0,0 +1,745 @@ +/* + * 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 "internal-gift64.h" +#include "internal-util.h" +#include + +/* Round constants for GIFT-64 in the fixsliced representation */ +static uint32_t const GIFT64_RC[28] = { + 0x22000011, 0x00002299, 0x11118811, 0x880000ff, 0x33111199, 0x990022ee, + 0x22119933, 0x880033bb, 0x22119999, 0x880022ff, 0x11119922, 0x880033cc, + 0x33008899, 0x99002299, 0x33118811, 0x880000ee, 0x33110099, 0x990022aa, + 0x22118833, 0x880022bb, 0x22111188, 0x88002266, 0x00009922, 0x88003300, + 0x22008811, 0x00002288, 0x00118811, 0x880000bb +}; + +int gift64b_init + (gift64b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + ks->k[0] = be_load_word32(key); + ks->k[1] = be_load_word32(key + 4); + ks->k[2] = be_load_word32(key + 8); + ks->k[3] = be_load_word32(key + 12); + gift64b_update_round_keys(ks); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift64b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t t = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= t; \ + (a) ^= t << (shift); \ + } while (0) + +/** + * \brief Performs the GIFT-64 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift64b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-64 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift64b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/* Rotates a state word left by 1 position in the fixsliced representation: + * + * 0 1 2 3 1 2 3 0 + * 4 5 6 7 ==> 5 6 7 4 + * 8 9 10 11 9 10 11 8 + * 12 13 14 15 13 14 14 12 + */ +#define gift64b_rotate_left_1(x) \ + ((((x) >> 1) & 0x77777777U) | (((x) & 0x11111111U) << 3)) + +/* Rotates a state word left by 2 positions in the fixsliced representation: + * + * 0 1 2 3 2 3 0 1 + * 4 5 6 7 ==> 6 7 4 5 + * 8 9 10 11 10 11 8 9 + * 12 13 14 15 14 15 12 13 + */ +#define gift64b_rotate_left_2(x) \ + ((((x) >> 2) & 0x33333333U) | (((x) & 0x33333333U) << 2)) + +/* Rotates a state word left by 3 positions in the fixsliced representation: + * + * 0 1 2 3 3 0 1 2 + * 4 5 6 7 ==> 7 4 5 6 + * 8 9 10 11 11 8 9 10 + * 12 13 14 15 15 12 13 14 + */ +#define gift64b_rotate_left_3(x) \ + ((((x) >> 3) & 0x11111111U) | (((x) & 0x77777777U) << 1)) + +/* Rotates a state word right by 1 position in the fixsliced representation */ +#define gift64b_rotate_right_1(x) gift64b_rotate_left_3(x) + +/* Rotates a state word right by 2 positions in the fixsliced representation */ +#define gift64b_rotate_right_2(x) gift64b_rotate_left_2(x) + +/* Rotates a state word right by 3 positions in the fixsliced representation */ +#define gift64b_rotate_right_3(x) gift64b_rotate_left_1(x) + +/* Rotates a state word up by 1 position in the fixsliced representation: + * + * 0 1 2 3 4 5 6 7 + * 4 5 6 7 ==> 8 9 10 11 + * 8 9 10 11 12 13 14 15 + * 12 13 14 15 0 1 2 3 + */ +#define gift64b_rotate_up_1(x) (rightRotate8((x))) + +/* Rotates a state word up by 2 positions in the fixsliced representation: + * + * 0 1 2 3 8 9 10 11 + * 4 5 6 7 ==> 12 13 14 15 + * 8 9 10 11 0 1 2 3 + * 12 13 14 15 4 5 6 7 + */ +#define gift64b_rotate_up_2(x) (rightRotate16((x))) + +/* Rotates a state word up by 3 positions in the fixsliced representation: + * + * 0 1 2 3 12 13 14 15 + * 4 5 6 7 ==> 0 1 2 3 + * 8 9 10 11 4 5 6 7 + * 12 13 14 15 8 9 10 11 + */ +#define gift64b_rotate_up_3(x) (rightRotate24((x))) + +/* Rotates a state word down by 1 position in the fixsliced representation */ +#define gift64b_rotate_down_1(x) gift64b_rotate_up_3(x) + +/* Rotates a state word down by 2 positions in the fixsliced representation */ +#define gift64b_rotate_down_2(x) gift64b_rotate_up_2(x) + +/* Rotates a state word down by 3 positions in the fixsliced representation */ +#define gift64b_rotate_down_3(x) gift64b_rotate_up_1(x) + +/* Permutation code to rearrange key bits into fixsliced form. Permutations + * generated wth "http://programming.sirrida.de/calcperm.php" */ +#define gift64b_rearrange1_transpose_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 8 16 24 3 11 19 27 2 10 18 26 1 9 17 25 * */ \ + bit_permute_step(out, 0x0000CCCCU, 16); \ + bit_permute_step(out, 0x30030330U, 2); \ + bit_permute_step(out, 0x00960096U, 8); \ + bit_permute_step(out, 0x05500550U, 1); \ + bit_permute_step(out, 0x0A0A0A0AU, 4); \ + } while (0) +#define gift64b_rearrange1_transpose_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 8 16 24 3 11 19 27 2 10 18 26 1 9 17 25 * */ \ + bit_permute_step(out, 0x0000CCCCU, 16); \ + bit_permute_step(out, 0x30030330U, 2); \ + bit_permute_step(out, 0x00960096U, 8); \ + bit_permute_step(out, 0x05500550U, 1); \ + bit_permute_step(out, 0x0A0A0A0AU, 4); \ + } while (0) +#define gift64b_rearrange1_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 1 2 3 24 25 26 27 16 17 18 19 8 9 10 11 * */ \ + out = (out & 0x0000000FU) | ((out & 0x00000F00U) << 8) | \ + ((out & 0x000000F0U) << 20) | ((out & 0x0000F000U) >> 4); \ + } while (0) +#define gift64b_rearrange1_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 1 2 3 24 25 26 27 16 17 18 19 8 9 10 11 * */ \ + out = (out & 0x0000000FU) | ((out & 0x00000F00U) << 8) | \ + ((out & 0x000000F0U) << 20) | ((out & 0x0000F000U) >> 4); \ + } while (0) +#define gift64b_rearrange2_transpose_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 * */ \ + bit_permute_step(out, 0x0A0A0A0AU, 3); \ + bit_permute_step(out, 0x00CC00CCU, 6); \ + bit_permute_step(out, 0x0000F0F0U, 12); \ + bit_permute_step(out, 0x0000FF00U, 8); \ + } while (0) +#define gift64b_rearrange2_transpose_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 * */ \ + bit_permute_step(out, 0x0A0A0A0AU, 3); \ + bit_permute_step(out, 0x00CC00CCU, 6); \ + bit_permute_step(out, 0x0000F0F0U, 12); \ + bit_permute_step(out, 0x0000FF00U, 8); \ + } while (0) +#define gift64b_rearrange2_low(out, in) \ + do { \ + out = (in) & 0x0000FFFFU; \ + /* 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 * */ \ + out = (out & 0x0000000FU) | ((out & 0x000000F0U) << 4) | \ + ((out & 0x00000F00U) << 8) | ((out & 0x0000F000U) << 12); \ + } while (0) +#define gift64b_rearrange2_high(out, in) \ + do { \ + out = (in) >> 16; \ + /* 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 * */ \ + out = (out & 0x0000000FU) | ((out & 0x000000F0U) << 4) | \ + ((out & 0x00000F00U) << 8) | ((out & 0x0000F000U) << 12); \ + } while (0) + +void gift64b_update_round_keys(gift64b_key_schedule_t *ks) +{ + uint32_t x; + + /* First round */ + gift64b_rearrange1_transpose_low(x, ks->k[3]); + ks->rk[0] = ~(x | (x << 4)); + gift64b_rearrange1_transpose_high(x, ks->k[3]); + ks->rk[1] = x | (x << 4); + + /* Second round */ + gift64b_rearrange1_low(x, ks->k[2]); + x = x | (x << 4); + gift64b_swap_move(x, x, 0x22222222U, 2); + ks->rk[2] = ~x; + gift64b_rearrange1_high(x, ks->k[2]); + x = x | (x << 4); + gift64b_swap_move(x, x, 0x22222222U, 2); + ks->rk[3] = x; + + /* Third round */ + gift64b_rearrange2_transpose_low(x, ks->k[1]); + gift64b_swap_move(x, x, 0x00000F00U, 16); + ks->rk[4] = ~(x | (x << 4)); + gift64b_rearrange2_transpose_high(x, ks->k[1]); + gift64b_swap_move(x, x, 0x00000F00U, 16); + ks->rk[5] = x | (x << 4); + + /* Fourth round */ + gift64b_rearrange2_low(x, ks->k[0]); + ks->rk[6] = ~(x | (x << 4)); + gift64b_rearrange2_high(x, ks->k[0]); + ks->rk[7] = x | (x << 4); +} + +/** + * \brief Perform the core of GIFT-64 encryption on two blocks in parallel. + * + * \param ks Points to the key schedule to use to encrypt the blocks. + * \param state Buffer containing the two blocks in bit-sliced form, + * on input and output. + * \param Tweak value or zero if there is no tweak. + */ +static void gift64b_encrypt_core + (const gift64b_key_schedule_t *ks, uint32_t state[4], uint32_t tweak) +{ + const uint32_t *rc = GIFT64_RC; + uint32_t s0, s1, s2, s3, temp; + uint32_t rk[8]; + uint8_t round; + + /* Start with the pre-computed round keys for the first four rounds */ + memcpy(rk, ks->rk, sizeof(ks->rk)); + + /* Load the state into local variables */ + s0 = state[0]; + s1 = state[1]; + s2 = state[2]; + s3 = state[3]; + + /* Perform all 28 rounds four at a time. We use the "fixslicing" method. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of four rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 4 rounds. + */ + for (round = 0; round < 28; round += 4, rc += 4) { + /* 1st round - S-box, rotate left, add round key */ + gift64b_sbox(s0, s1, s2, s3); + s1 = gift64b_rotate_left_1(s1); + s2 = gift64b_rotate_left_2(s2); + s0 = gift64b_rotate_left_3(s0); + s3 ^= rk[0]; + s1 ^= rk[1]; + s0 ^= rc[0]; + + /* 2nd round - S-box, rotate up, add round key (s0 and s3 swapped) */ + gift64b_sbox(s3, s1, s2, s0); + s1 = gift64b_rotate_up_1(s1); + s2 = gift64b_rotate_up_2(s2); + s3 = gift64b_rotate_up_3(s3); + s0 ^= rk[2]; + s1 ^= rk[3]; + s3 ^= rc[1]; + + /* 3rd round - S-box, rotate right, add round key */ + gift64b_sbox(s0, s1, s2, s3); + s1 = gift64b_rotate_right_1(s1); + s2 = gift64b_rotate_right_2(s2); + s0 = gift64b_rotate_right_3(s0); + s3 ^= rk[4]; + s1 ^= rk[5]; + s0 ^= rc[2]; + + /* 4th round - S-box, rotate down, add round key (s0 and s3 swapped) */ + gift64b_sbox(s3, s1, s2, s0); + s1 = gift64b_rotate_down_1(s1); + s2 = gift64b_rotate_down_2(s2); + s3 = gift64b_rotate_down_3(s3); + s0 ^= rk[6]; + s1 ^= rk[7]; + s3 ^= rc[3]; + + /* Add the tweak every four encryption rounds except the last */ + if (round < 24) + s2 ^= tweak; + + /* Derive the round keys for the next 4 rounds */ + rk[0] = gift64b_rotate_left_1(rk[0]); + rk[1] = (gift64b_rotate_left_3(rk[1]) << 16) | (rk[1] >> 16); + rk[2] = rightRotate8(rk[2]); + temp = gift64b_rotate_left_2(rk[3]); + rk[3] = (temp & 0x99999999U) | leftRotate8(temp & 0x66666666U); + rk[4] = gift64b_rotate_left_3(rk[4]); + temp = rightRotate16(rk[5]); + rk[5] = (gift64b_rotate_left_1(temp) & 0x00FFFF00U) | + (temp & 0xFF0000FFU); + rk[6] = leftRotate8(rk[6]); + temp = gift64b_rotate_left_2(rk[7]); + rk[7] = (temp & 0x33333333U) | rightRotate8(temp & 0xCCCCCCCCU); + } + + /* Copy the local variables to the output state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} + +/** + * \brief Perform the core of GIFT-64 decryption on two blocks in parallel. + * + * \param ks Points to the key schedule to use to encrypt the blocks. + * \param state Buffer containing the two blocks in bit-sliced form, + * on input and output. + * \param Tweak value or zero if there is no tweak. + */ +static void gift64b_decrypt_core + (const gift64b_key_schedule_t *ks, uint32_t state[4], uint32_t tweak) +{ + const uint32_t *rc = GIFT64_RC + 28 - 4; + uint32_t s0, s1, s2, s3, temp; + uint32_t rk[8]; + uint8_t round; + + /* Start with the pre-computed round keys for the first four rounds */ + memcpy(rk, ks->rk, sizeof(ks->rk)); + + /* Fast forward the key schedule to the end by permuting each round + * key by the amount it would see under the full set of rounds. + * Generated with "http://programming.sirrida.de/calcperm.php" */ + /* P0: 1 2 3 0 5 6 7 4 9 10 11 8 13 14 15 12 17 18 + * 19 16 21 22 23 20 25 26 27 24 29 30 31 28 */ + rk[0] = ((rk[0] & 0x77777777U) << 1) | ((rk[0] & 0x88888888U) >> 3); + /* P1: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + * 31 3 0 1 2 7 4 5 6 11 8 9 10 15 12 13 14 */ + rk[1] = ((rk[1] & 0xEEEE0000U) >> 17) | ((rk[1] & 0x0000FFFFU) << 16) | + ((rk[1] & 0x11110000U) >> 13); + /* P2: 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + * 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 */ + rk[2] = leftRotate8(rk[2]); + /* P3: 2 27 24 1 6 31 28 5 10 3 0 9 14 7 4 13 18 11 + * 8 17 22 15 12 21 26 19 16 25 30 23 20 29 */ + rk[3] = ((rk[3] & 0x11111111U) << 2) | leftRotate22(rk[3] & 0x44444444U) | + leftRotate26(rk[3] & 0x22222222U) | ((rk[3] & 0x88888888U) >> 2); + /* P4: 3 0 1 2 7 4 5 6 11 8 9 10 15 12 13 14 19 16 + * 17 18 23 20 21 22 27 24 25 26 31 28 29 30 */ + rk[4] = ((rk[4] & 0x11111111U) << 3) | ((rk[4] & 0xEEEEEEEEU) >> 1); + /* P5: 16 17 18 19 20 21 22 23 25 26 27 24 29 30 31 + * 28 1 2 3 0 5 6 7 4 8 9 10 11 12 13 14 15 */ + rk[5] = leftRotate13(rk[5] & 0x00888800U) | + leftRotate16(rk[5] & 0xFF0000FFU) | + leftRotate17(rk[5] & 0x00777700U); + /* P6: 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 8 9 10 + * 11 12 13 14 15 16 17 18 19 20 21 22 23 */ + rk[6] = leftRotate24(rk[6]); + /* P7: 2 3 8 9 6 7 12 13 10 11 16 17 14 15 20 21 18 19 + * 24 25 22 23 28 29 26 27 0 1 30 31 4 5 */ + rk[7] = ((rk[7] & 0x33333333U) << 2) | leftRotate6(rk[7] & 0xCCCCCCCCU); + + /* Load the state into local variables */ + s0 = state[0]; + s1 = state[1]; + s2 = state[2]; + s3 = state[3]; + + /* Perform all 28 rounds four at a time. We use the "fixslicing" method. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of four rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 4 rounds. + */ + for (round = 0; round < 28; round += 4, rc -= 4) { + /* Derive the round keys for the previous 4 rounds */ + rk[0] = gift64b_rotate_right_1(rk[0]); + temp = rk[1] >> 16; + rk[1] = gift64b_rotate_right_3(temp) | (rk[1] << 16); + rk[2] = leftRotate8(rk[2]); + temp = (rk[3] & 0x99999999U) | rightRotate8(rk[3] & 0x66666666U); + rk[3] = gift64b_rotate_right_2(temp); + rk[4] = gift64b_rotate_right_3(rk[4]); + temp = (gift64b_rotate_right_1(rk[5]) & 0x00FFFF00U) | + (rk[5] & 0xFF0000FFU); + rk[5] = leftRotate16(temp); + rk[6] = rightRotate8(rk[6]); + temp = (rk[7] & 0x33333333U) | leftRotate8(rk[7] & 0xCCCCCCCCU); + rk[7] = gift64b_rotate_right_2(temp); + + /* Add the tweak every four decryption rounds except the first */ + if (round != 0) + s2 ^= tweak; + + /* 4th round - S-box, rotate down, add round key (s0 and s3 swapped) */ + s0 ^= rk[6]; + s1 ^= rk[7]; + s3 ^= rc[3]; + s1 = gift64b_rotate_up_1(s1); + s2 = gift64b_rotate_up_2(s2); + s3 = gift64b_rotate_up_3(s3); + gift64b_inv_sbox(s0, s1, s2, s3); + + /* 3rd round - S-box, rotate right, add round key */ + s3 ^= rk[4]; + s1 ^= rk[5]; + s0 ^= rc[2]; + s1 = gift64b_rotate_left_1(s1); + s2 = gift64b_rotate_left_2(s2); + s0 = gift64b_rotate_left_3(s0); + gift64b_inv_sbox(s3, s1, s2, s0); + + /* 2nd round - S-box, rotate up, add round key (s0 and s3 swapped) */ + s0 ^= rk[2]; + s1 ^= rk[3]; + s3 ^= rc[1]; + s1 = gift64b_rotate_down_1(s1); + s2 = gift64b_rotate_down_2(s2); + s3 = gift64b_rotate_down_3(s3); + gift64b_inv_sbox(s0, s1, s2, s3); + + /* 1st round - S-box, rotate left, add round key */ + s3 ^= rk[0]; + s1 ^= rk[1]; + s0 ^= rc[0]; + s1 = gift64b_rotate_right_1(s1); + s2 = gift64b_rotate_right_2(s2); + s0 = gift64b_rotate_right_3(s0); + gift64b_inv_sbox(s3, s1, s2, s0); + } + + /* Copy the local variables to the output state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} + +int gift64n_init + (gift64n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian byte order from the LOTUS-AEAD submission */ + if (!ks || !key || key_len != 16) + return 0; + ks->k[0] = le_load_word32(key + 12); + ks->k[1] = le_load_word32(key + 8); + ks->k[2] = le_load_word32(key + 4); + ks->k[3] = le_load_word32(key); + gift64b_update_round_keys(ks); + return 1; +} + +/** + * \brief Converts the GIFT-64 nibble-based representation into word-based + * (littlen-endian version). + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The output words will be in fixsliced form. Technically the output will + * contain two blocks for gift64b_encrypt_core() to process in parallel but + * both blocks will have the same value. + */ +static void gift64n_to_words(uint32_t output[4], const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input block into 32-bit words */ + s0 = le_load_word32(input); + s2 = le_load_word32(input + 4); + + /* Rearrange the bits in the block */ + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + + /* Split into two identical blocks in fixsliced form */ + s1 = s0; + s3 = s2; + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +/** + * \brief Converts the GIFT-64 word-based representation into nibble-based + * (little-endian version). + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + * + * The input words are in fixsliced form. Technically there are two + * identical blocks in the input. We drop one when we write to the output. + */ +static void gift64n_to_nibbles(unsigned char *output, const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Load the state and split the two blocks into separate words */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + + /* Rearrange the bits in the first block back into nibble form */ + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + le_store_word32(output, s0); + le_store_word32(output + 4, s2); +} + +void gift64n_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_encrypt_core(ks, state, 0); + gift64n_to_nibbles(output, state); +} + +void gift64n_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_decrypt_core(ks, state, 0); + gift64n_to_nibbles(output, state); +} + +/** + * \brief Converts the GIFT-64 nibble-based representation into word-based + * (big-endian version). + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The output words will be in fixsliced form. Technically the output will + * contain two blocks for gift64b_encrypt_core() to process in parallel but + * both blocks will have the same value. + */ +static void gift64nb_to_words(uint32_t output[4], const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input block into 32-bit words */ + s0 = be_load_word32(input + 4); + s2 = be_load_word32(input); + + /* Rearrange the bits in the block */ + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + + /* Split into two identical blocks in fixsliced form */ + s1 = s0; + s3 = s2; + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +/** + * \brief Converts the GIFT-64 word-based representation into nibble-based + * (big-endian version). + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + * + * The input words are in fixsliced form. Technically there are two + * identical blocks in the input. We drop one when we write to the output. + */ +static void gift64nb_to_nibbles(unsigned char *output, const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Load the state and split the two blocks into separate words */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + gift64b_swap_move(s0, s2, 0x0000FFFFU, 16); + gift64b_swap_move(s1, s3, 0x0000FFFFU, 16); + gift64b_swap_move(s0, s1, 0x0F0F0F0FU, 4); + gift64b_swap_move(s2, s3, 0x0F0F0F0FU, 4); + + /* Rearrange the bits in the first block back into nibble form */ + gift64b_swap_move(s0, s0, 0x0000FF00U, 8); + gift64b_swap_move(s0, s0, 0x00CC00CCU, 6); + gift64b_swap_move(s0, s0, 0x0A0A0A0AU, 3); + gift64b_swap_move(s2, s2, 0x0000FF00U, 8); + gift64b_swap_move(s2, s2, 0x00CC00CCU, 6); + gift64b_swap_move(s2, s2, 0x0A0A0A0AU, 3); + be_store_word32(output, s2); + be_store_word32(output + 4, s0); +} + +void gift64nb_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64nb_to_words(state, input); + gift64b_encrypt_core(ks, state, 0); + gift64nb_to_nibbles(output, state); +} + +void gift64nb_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t state[4]; + gift64nb_to_words(state, input); + gift64b_decrypt_core(ks, state, 0); + gift64nb_to_nibbles(output, state); +} + +/* 4-bit tweak values expanded to 32-bit in fixsliced form */ +static uint32_t const GIFT64_tweaks[16] = { + 0x00000000, 0xee11ee11, 0xdd22dd22, 0x33333333, 0xbb44bb44, 0x55555555, + 0x66666666, 0x88778877, 0x77887788, 0x99999999, 0xaaaaaaaa, 0x44bb44bb, + 0xcccccccc, 0x22dd22dd, 0x11ee11ee, 0xffffffff +}; + +void gift64t_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_encrypt_core(ks, state, GIFT64_tweaks[tweak]); + gift64n_to_nibbles(output, state); +} + +void gift64t_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t state[4]; + gift64n_to_words(state, input); + gift64b_decrypt_core(ks, state, GIFT64_tweaks[tweak]); + gift64n_to_nibbles(output, state); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.h b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.h new file mode 100644 index 0000000..40479c7 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-gift64.h @@ -0,0 +1,194 @@ +/* + * 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_GIFT64_H +#define LW_INTERNAL_GIFT64_H + +/** + * \file internal-gift64.h + * \brief GIFT-64 block cipher. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-64 block in bytes. + */ +#define GIFT64_BLOCK_SIZE 8 + +/** + * \brief Structure of the key schedule for GIFT-64 (bit-sliced). + */ +typedef struct +{ + uint32_t k[4]; /**< Words of the key schedule */ + uint32_t rk[8]; /**< Pre-computed round keys for fixsliced form */ + +} gift64b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-64 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift64b_init + (gift64b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Updates the round keys after a change in the base key. + * + * \param ks Points to the key schedule to update. + */ +void gift64b_update_round_keys(gift64b_key_schedule_t *ks); + +/** + * \brief Structure of the key schedule for GIFT-64 (nibble-based). + */ +typedef gift64b_key_schedule_t gift64n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-64 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift64n_init + (gift64n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 64-bit block with GIFT-64 (nibble-based). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void gift64n_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 64-bit block with GIFT-64 (nibble-based). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + */ +void gift64n_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with GIFT-64 (nibble-based big-endian). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + */ +void gift64nb_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 64-bit block with GIFT-64 (nibble-based big-endian). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + */ +void gift64nb_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 64-bit block with TweGIFT-64 (tweakable variant). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * \param tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-64 is used by the LOTUS/LOCUS submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift64n_encrypt(). + */ +void gift64t_encrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 64-bit block with TweGIFT-64 (tweakable variant). + * + * \param ks Points to the GIFT-64 key schedule. + * \param output Output buffer which must be at least 8 bytes in length. + * \param input Input buffer which must be at least 8 bytes in length. + * \param tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-64 is used by the LOTUS/LOCUS submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift64n_decrypt(). + */ +void gift64t_decrypt + (const gift64n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-util.h b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.c b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.c new file mode 100644 index 0000000..e60b084 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.c @@ -0,0 +1,436 @@ +/* + * 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 "lotus-locus.h" +#include "internal-gift64.h" +#include "internal-util.h" +#include + +aead_cipher_t const lotus_aead_cipher = { + "LOTUS-AEAD", + LOTUS_AEAD_KEY_SIZE, + LOTUS_AEAD_NONCE_SIZE, + LOTUS_AEAD_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + lotus_aead_encrypt, + lotus_aead_decrypt +}; + +aead_cipher_t const locus_aead_cipher = { + "LOCUS-AEAD", + LOCUS_AEAD_KEY_SIZE, + LOCUS_AEAD_NONCE_SIZE, + LOCUS_AEAD_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + locus_aead_encrypt, + locus_aead_decrypt +}; + +/** + * \brief Multiplies a key by 2 in the GF(128) field. + * + * \param ks The key schedule structure containing the key in host byte order. + */ +STATIC_INLINE void lotus_or_locus_mul_2(gift64n_key_schedule_t *ks) +{ + uint32_t mask = (uint32_t)(((int32_t)(ks->k[0])) >> 31); + ks->k[0] = (ks->k[0] << 1) | (ks->k[1] >> 31); + ks->k[1] = (ks->k[1] << 1) | (ks->k[2] >> 31); + ks->k[2] = (ks->k[2] << 1) | (ks->k[3] >> 31); + ks->k[3] = (ks->k[3] << 1) ^ (mask & 0x87); + gift64b_update_round_keys(ks); +} + +/** + * \brief Initializes a LOTUS-AEAD or LOCUS-AEAD cipher instance. + * + * \param ks Key schedule to initialize. + * \param deltaN Delta-N value for the cipher state. + * \param key Points to the 16-byte key for the cipher instance. + * \param nonce Points to the 16-byte key for the cipher instance. + * \param T Points to a temporary buffer of LOTUS_AEAD_KEY_SIZE bytes + * that will be destroyed during this function. + */ +static void lotus_or_locus_init + (gift64n_key_schedule_t *ks, + unsigned char deltaN[GIFT64_BLOCK_SIZE], + const unsigned char *key, + const unsigned char *nonce, + unsigned char *T) +{ + gift64n_init(ks, key, LOTUS_AEAD_KEY_SIZE); + memset(deltaN, 0, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, deltaN, deltaN, 0); + lw_xor_block_2_src(T, key, nonce, LOTUS_AEAD_KEY_SIZE); + gift64n_init(ks, T, LOTUS_AEAD_KEY_SIZE); + gift64t_encrypt(ks, deltaN, deltaN, 1); +} + +/** + * \brief Processes associated data for LOTUS-AEAD or LOCUS-AEAD. + * + * \param ks Points to the key schedule. + * \param deltaN Points to the Delta-N value from the state. + * \param V Points to the V value from the state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void lotus_or_locus_process_ad + (gift64n_key_schedule_t *ks, + const unsigned char deltaN[GIFT64_BLOCK_SIZE], + unsigned char V[GIFT64_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned char temp; + while (adlen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(ks); + lw_xor_block_2_src(X, ad, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, X, X, 2); + lw_xor_block(V, X, GIFT64_BLOCK_SIZE); + ad += GIFT64_BLOCK_SIZE; + adlen -= GIFT64_BLOCK_SIZE; + } + lotus_or_locus_mul_2(ks); + temp = (unsigned)adlen; + if (temp < GIFT64_BLOCK_SIZE) { + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(X, ad, temp); + X[temp] ^= 0x01; + gift64t_encrypt(ks, X, X, 3); + } else { + lw_xor_block_2_src(X, ad, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, X, X, 2); + } + lw_xor_block(V, X, GIFT64_BLOCK_SIZE); +} + +/** + * \brief Generates the authentication tag for LOTUS-AEAD or LOCUS-AEAD. + * + * \param ks Points to the key schedule. + * \param tag Points to the buffer to receive the authentication tag. + * \param deltaN Points to the Delta-N value from the state. + * \param W Points to the W value from the state. + * \param V Points to the V value from the state. + */ +static void lotus_or_locus_gen_tag + (gift64n_key_schedule_t *ks, unsigned char *tag, + unsigned char deltaN[GIFT64_BLOCK_SIZE], + unsigned char W[GIFT64_BLOCK_SIZE], + unsigned char V[GIFT64_BLOCK_SIZE]) +{ + lotus_or_locus_mul_2(ks); + lw_xor_block(W, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(W, V, GIFT64_BLOCK_SIZE); + gift64t_encrypt(ks, W, W, 6); + lw_xor_block_2_src(tag, W, deltaN, GIFT64_BLOCK_SIZE); +} + +int lotus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X1[GIFT64_BLOCK_SIZE]; + unsigned char X2[GIFT64_BLOCK_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + LOTUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > (GIFT64_BLOCK_SIZE * 2)) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X1, m, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X1, 4); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block_2_src + (X2, m + GIFT64_BLOCK_SIZE, X2, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(c, X2, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block_2_src + (c + GIFT64_BLOCK_SIZE, X1, X2, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE * 2; + m += GIFT64_BLOCK_SIZE * 2; + mlen -= GIFT64_BLOCK_SIZE * 2; + } + temp = (unsigned)mlen; + lotus_or_locus_mul_2(&ks); + memcpy(X1, deltaN, GIFT64_BLOCK_SIZE); + X1[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X2, X1, 12); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 12); + if (temp <= GIFT64_BLOCK_SIZE) { + lw_xor_block(WV, m, temp); + lw_xor_block(X2, m, temp); + lw_xor_block_2_src(c, X2, deltaN, temp); + } else { + lw_xor_block(X2, m, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(c, X2, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + temp -= GIFT64_BLOCK_SIZE; + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, m, temp); + lw_xor_block(X1, X2, temp); + lw_xor_block_2_src(c, X1, m, temp); + } + c += temp; + } + + /* Generate the authentication tag */ + lotus_or_locus_gen_tag(&ks, c, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return 0; +} + +int lotus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X1[GIFT64_BLOCK_SIZE]; + unsigned char X2[GIFT64_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < LOTUS_AEAD_TAG_SIZE) + return -1; + *mlen = clen - LOTUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= LOTUS_AEAD_TAG_SIZE; + if (clen > 0) { + while (clen > (GIFT64_BLOCK_SIZE * 2)) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X1, c, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X1, 5); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 5); + lw_xor_block(X2, c + GIFT64_BLOCK_SIZE, GIFT64_BLOCK_SIZE); + lw_xor_block_2_src(m, X2, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 4); + lw_xor_block_2_src + (m + GIFT64_BLOCK_SIZE, X1, X2, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE * 2; + m += GIFT64_BLOCK_SIZE * 2; + clen -= GIFT64_BLOCK_SIZE * 2; + } + temp = (unsigned)clen; + lotus_or_locus_mul_2(&ks); + memcpy(X1, deltaN, GIFT64_BLOCK_SIZE); + X1[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X2, X1, 12); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 12); + if (temp <= GIFT64_BLOCK_SIZE) { + lw_xor_block_2_src(m, X2, c, temp); + lw_xor_block(m, deltaN, temp); + lw_xor_block(X2, m, temp); + lw_xor_block(WV, m, temp); + } else { + lw_xor_block_2_src(m, X2, c, GIFT64_BLOCK_SIZE); + lw_xor_block(m, deltaN, GIFT64_BLOCK_SIZE); + lw_xor_block(X2, m, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + temp -= GIFT64_BLOCK_SIZE; + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(WV, X2, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X2, X2, 13); + lw_xor_block(X1, X2, temp); + lw_xor_block_2_src(m, X1, c, temp); + lw_xor_block(WV, m, temp); + } + c += temp; + } + + /* Check the authentication tag */ + lotus_or_locus_gen_tag(&ks, WV, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return aead_check_tag(mtemp, *mlen, WV, c, LOTUS_AEAD_TAG_SIZE); +} + +int locus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + LOCUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X, m, deltaN, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 4); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 4); + lw_xor_block_2_src(c, X, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + mlen -= GIFT64_BLOCK_SIZE; + } + temp = (unsigned)mlen; + lotus_or_locus_mul_2(&ks); + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + X[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + lw_xor_block(WV, m, temp); + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(X, deltaN, temp); + lw_xor_block_2_src(c, m, X, temp); + c += temp; + } + + /* Generate the authentication tag */ + lotus_or_locus_gen_tag(&ks, c, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return 0; +} + +int locus_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) +{ + gift64n_key_schedule_t ks; + unsigned char WV[GIFT64_BLOCK_SIZE * 2]; + unsigned char deltaN[GIFT64_BLOCK_SIZE]; + unsigned char X[GIFT64_BLOCK_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < LOCUS_AEAD_TAG_SIZE) + return -1; + *mlen = clen - LOCUS_AEAD_TAG_SIZE; + + /* Initialize the state with the key and the nonce */ + lotus_or_locus_init(&ks, deltaN, k, npub, WV); + memset(WV, 0, sizeof(WV)); + + /* Process the associated data */ + if (adlen > 0) { + lotus_or_locus_process_ad + (&ks, deltaN, WV + GIFT64_BLOCK_SIZE, ad, adlen); + } + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= LOCUS_AEAD_TAG_SIZE; + if (clen > 0) { + while (clen > GIFT64_BLOCK_SIZE) { + lotus_or_locus_mul_2(&ks); + lw_xor_block_2_src(X, c, deltaN, GIFT64_BLOCK_SIZE); + gift64t_decrypt(&ks, X, X, 4); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_decrypt(&ks, X, X, 4); + lw_xor_block_2_src(m, X, deltaN, GIFT64_BLOCK_SIZE); + c += GIFT64_BLOCK_SIZE; + m += GIFT64_BLOCK_SIZE; + clen -= GIFT64_BLOCK_SIZE; + } + temp = (unsigned)clen; + lotus_or_locus_mul_2(&ks); + memcpy(X, deltaN, GIFT64_BLOCK_SIZE); + X[0] ^= (unsigned char)temp; + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(WV, X, GIFT64_BLOCK_SIZE); + gift64t_encrypt(&ks, X, X, 5); + lw_xor_block(X, deltaN, temp); + lw_xor_block_2_src(m, c, X, temp); + lw_xor_block(WV, m, temp); + c += temp; + } + + /* Check the authentication tag */ + lotus_or_locus_gen_tag(&ks, WV, deltaN, WV, WV + GIFT64_BLOCK_SIZE); + return aead_check_tag(mtemp, *mlen, WV, c, LOCUS_AEAD_TAG_SIZE); +} diff --git a/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.h b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.h new file mode 100644 index 0000000..85434a8 --- /dev/null +++ b/lotus-locus/Implementations/crypto_aead/twegift64lotusaeadv1/rhys/lotus-locus.h @@ -0,0 +1,223 @@ +/* + * 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_LOTUS_LOCUS_H +#define LWCRYPTO_LOTUS_LOCUS_H + +#include "aead-common.h" + +/** + * \file lotus-locus.h + * \brief LOTUS-AEAD and LOCUS-AEAD authenticated encryption algorithms. + * + * LOTUS-AEAD and LOCUS-AEAD are authenticated encryption algorithms + * that are based around a tweakable variant of the GIFT-64 block cipher + * called TweGIFT-64. Both AEAD algorithms have a 128-bit key, a 128-bit + * nonce, and a 64-bit tag. + * + * The two algorithms have the same key initialization, associated data + * processing, and tag generation mechanisms. They differ in how the + * input is encrypted with TweGIFT-64. + * + * LOTUS-AEAD uses a method similar to the block cipher mode OTR. + * TweGIFT-64 is essentially converted into a 128-bit block cipher + * using a Feistel construction and four TweGIFT-64 block operations + * every 16 bytes of input. + * + * LOCUS-AEAD uses a method similar to the block cipher mode OCB + * with two TweGIFT-64 block operations for every 8 bytes of input. + * LOCUS-AEAD requires both the block encrypt and block decrypt + * operations of TweGIFT-64, which increases the overall code size. + * LOTUS-AEAD only needs the block encrypt operation. + * + * LOTUS-AEAD is the primary member of the family. + * + * References: https://www.isical.ac.in/~lightweight/lotus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for LOTUS-AEAD. + */ +#define LOTUS_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for LOTUS-AEAD. + */ +#define LOTUS_AEAD_TAG_SIZE 8 + +/** + * \brief Size of the nonce for LOTUS-AEAD. + */ +#define LOTUS_AEAD_NONCE_SIZE 16 + +/** + * \brief Size of the key for LOCUS-AEAD. + */ +#define LOCUS_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for LOCUS-AEAD. + */ +#define LOCUS_AEAD_TAG_SIZE 8 + +/** + * \brief Size of the nonce for LOCUS-AEAD. + */ +#define LOCUS_AEAD_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the LOTUS-AEAD cipher. + */ +extern aead_cipher_t const lotus_aead_cipher; + +/** + * \brief Meta-information block for the LOCUS-AEAD cipher. + */ +extern aead_cipher_t const locus_aead_cipher; + +/** + * \brief Encrypts and authenticates a packet with LOTUS-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa lotus_aead_decrypt() + */ +int lotus_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); + +/** + * \brief Decrypts and authenticates a packet with LOTUS-AEAD. + * + * \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 - not used by this algorithm. + * \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 9 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa lotus_aead_encrypt() + */ +int lotus_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); + +/** + * \brief Encrypts and authenticates a packet with LOCUS-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa locus_aead_decrypt() + */ +int locus_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); + +/** + * \brief Decrypts and authenticates a packet with LOCUS-AEAD. + * + * \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 - not used by this algorithm. + * \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 9 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa locus_aead_encrypt() + */ +int locus_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.c b/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.h b/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/api.h b/orange/Implementations/crypto_aead/orangezestv1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/encrypt.c b/orange/Implementations/crypto_aead/orangezestv1/rhys/encrypt.c new file mode 100644 index 0000000..e1ea967 --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "orange.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 orange_zest_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 orange_zest_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.c b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.c new file mode 100644 index 0000000..b8743fe --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.c @@ -0,0 +1,479 @@ +/* + * 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 "internal-photon256.h" +#include "internal-util.h" + +/** + * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. + */ +#define PHOTON256_ROUNDS 12 + +/* Round constants for PHOTON-256 */ +static uint32_t const photon256_rc[PHOTON256_ROUNDS] = { + 0x96d2f0e1, 0xb4f0d2c3, 0xf0b49687, 0x692d0f1e, + 0x5a1e3c2d, 0x3c785a4b, 0xe1a58796, 0x4b0f2d3c, + 0x1e5a7869, 0xa5e1c3d2, 0xd296b4a5, 0x2d694b5a +}; + +/** + * \brief Evaluates the PHOTON-256 S-box in bit-sliced form. + * + * \param x0 Slice with bit 0 of all nibbles. + * \param x1 Slice with bit 1 of all nibbles. + * \param x2 Slice with bit 2 of all nibbles. + * \param x3 Slice with bit 3 of all nibbles. + * + * This bit-sliced S-box implementation is based on the AVR version + * "add_avr8_bitslice_asm" from the PHOTON-Beetle reference code. + */ +#define photon256_sbox(x0, x1, x2, x3) \ + do { \ + x1 ^= x2; \ + x3 ^= (x2 & x1); \ + t1 = x3; \ + x3 = (x3 & x1) ^ x2; \ + t2 = x3; \ + x3 ^= x0; \ + x3 = ~(x3); \ + x2 = x3; \ + t2 |= x0; \ + x0 ^= t1; \ + x1 ^= x0; \ + x2 |= x1; \ + x2 ^= t1; \ + x1 ^= t2; \ + x3 ^= x1; \ + } while (0) + +/** + * \brief Performs a field multiplication on the 8 nibbles in a row. + * + * \param a Field constant to multiply by. + * \param x Bit-sliced form of the row, with bits 0..3 of each nibble + * in bytes 0..3 of the word. + * + * \return a * x packed into the bytes of a word. + */ +static uint32_t photon256_field_multiply(uint8_t a, uint32_t x) +{ + /* For each 4-bit nibble we need to do this: + * + * result = 0; + * for (bit = 0; bit < 4; ++ bit) { + * if ((a & (1 << bit)) != 0) + * result ^= x; + * if ((x & 0x08) != 0) { + * x = (x << 1) ^ 3; + * } else { + * x = (x << 1); + * } + * } + * + * We don't need to worry about constant time for "a" because it is a + * known constant that isn't data-dependent. But we do need to worry + * about constant time for "x" as it is data. + */ + uint32_t result = 0; + uint32_t t; + #define PARALLEL_CONDITIONAL_ADD(bit) \ + do { \ + if ((a) & (1 << (bit))) \ + result ^= x; \ + } while (0) + #define PARALELL_ROTATE() \ + do { \ + t = x >> 24; \ + x = (x << 8) ^ t ^ (t << 8); \ + } while (0) + PARALLEL_CONDITIONAL_ADD(0); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(1); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(2); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(3); + return result; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts a PHOTON-256 state into bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_to_sliced + (uint32_t out[PHOTON256_STATE_SIZE / 4], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* We first scatter bits 0..3 of the nibbles to bytes 0..3 of the words. + * Then we rearrange the bytes to group all bits N into word N. + * + * Permutation generated with "http://programming.sirrida.de/calcperm.php". + * + * P = [0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 + * 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31] + */ + uint32_t t0, t1, t2, t3; + #define TO_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + #define FROM_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + t0 = le_load_word32(in); + t1 = le_load_word32(in + 4); + t2 = le_load_word32(in + 8); + t3 = le_load_word32(in + 12); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[0] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[1] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[2] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[3] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); + t0 = le_load_word32(in + 16); + t1 = le_load_word32(in + 20); + t2 = le_load_word32(in + 24); + t3 = le_load_word32(in + 28); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[4] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[5] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[6] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[7] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); +} + +/** + * \brief Converts a PHOTON-256 state from bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_from_sliced + (unsigned char out[PHOTON256_STATE_SIZE], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* Do the reverse of photon256_to_sliced() */ + uint32_t x0, x1, x2, x3; + x0 = ((uint32_t)(in[0])) | + (((uint32_t)(in[4])) << 8) | + (((uint32_t)(in[8])) << 16) | + (((uint32_t)(in[12])) << 24); + x1 = ((uint32_t)(in[1])) | + (((uint32_t)(in[5])) << 8) | + (((uint32_t)(in[9])) << 16) | + (((uint32_t)(in[13])) << 24); + x2 = ((uint32_t)(in[2])) | + (((uint32_t)(in[6])) << 8) | + (((uint32_t)(in[10])) << 16) | + (((uint32_t)(in[14])) << 24); + x3 = ((uint32_t)(in[3])) | + (((uint32_t)(in[7])) << 8) | + (((uint32_t)(in[11])) << 16) | + (((uint32_t)(in[15])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out, x0); + le_store_word32(out + 4, x1); + le_store_word32(out + 8, x2); + le_store_word32(out + 12, x3); + x0 = ((uint32_t)(in[16])) | + (((uint32_t)(in[20])) << 8) | + (((uint32_t)(in[24])) << 16) | + (((uint32_t)(in[28])) << 24); + x1 = ((uint32_t)(in[17])) | + (((uint32_t)(in[21])) << 8) | + (((uint32_t)(in[25])) << 16) | + (((uint32_t)(in[29])) << 24); + x2 = ((uint32_t)(in[18])) | + (((uint32_t)(in[22])) << 8) | + (((uint32_t)(in[26])) << 16) | + (((uint32_t)(in[30])) << 24); + x3 = ((uint32_t)(in[19])) | + (((uint32_t)(in[23])) << 8) | + (((uint32_t)(in[27])) << 16) | + (((uint32_t)(in[31])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out + 16, x0); + le_store_word32(out + 20, x1); + le_store_word32(out + 24, x2); + le_store_word32(out + 28, x3); +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +/* Index the bit-sliced state bytes in little-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[(row)] = (uint8_t)(value); \ + S.bytes[(row) + 4] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 8] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 12] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[(row) + 12] = (uint8_t)(value); \ + S.bytes[(row) + 16] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 20] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 24] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#else +/* Index the bit-sliced state bytes in big-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[3 - (row)] = (uint8_t)(value); \ + S.bytes[7 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[11 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[15 - (row)] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[20 - (row)] = (uint8_t)(value); \ + S.bytes[24 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[28 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[32 - (row)] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#endif + +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) +{ + union { + uint32_t words[PHOTON256_STATE_SIZE / 4]; + uint8_t bytes[PHOTON256_STATE_SIZE]; + } S; + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + uint8_t round; + + /* Convert the state into bit-sliced form */ + photon256_to_sliced(S.words, state); + + /* Perform all 12 permutation rounds */ + for (round = 0; round < PHOTON256_ROUNDS; ++round) { + /* Add the constants for this round */ + t0 = photon256_rc[round]; + S.words[0] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[1] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[2] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[3] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[4] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[5] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[6] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[7] ^= t0 & 0x01010101U; + + /* Apply the sbox to all nibbles in the state */ + photon256_sbox(S.words[0], S.words[1], S.words[2], S.words[3]); + photon256_sbox(S.words[4], S.words[5], S.words[6], S.words[7]); + + /* Rotate all rows left by the row number. + * + * We do this by applying permutations to the top and bottom words + * to rearrange the bits into the rotated form. Permutations + * generated with "http://programming.sirrida.de/calcperm.php". + * + * P_top = [0 1 2 3 4 5 6 7 15 8 9 10 11 12 13 14 22 23 + * 16 17 18 19 20 21 29 30 31 24 25 26 27 28] + * P_bot = [4 5 6 7 0 1 2 3 11 12 13 14 15 8 9 10 18 19 + * 20 21 22 23 16 17 25 26 27 28 29 30 31 24 + */ + #define TOP_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x07030100, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + #define BOTTOM_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x080c0e0f, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + TOP_ROTATE_PERM(S.words[0]); + TOP_ROTATE_PERM(S.words[1]); + TOP_ROTATE_PERM(S.words[2]); + TOP_ROTATE_PERM(S.words[3]); + BOTTOM_ROTATE_PERM(S.words[4]); + BOTTOM_ROTATE_PERM(S.words[5]); + BOTTOM_ROTATE_PERM(S.words[6]); + BOTTOM_ROTATE_PERM(S.words[7]); + + /* Mix the columns */ + #define MUL(a, x) (photon256_field_multiply((a), (x))) + t0 = READ_ROW0(); + t1 = READ_ROW1(); + t2 = READ_ROW2(); + t3 = READ_ROW3(); + t4 = READ_ROW4(); + t5 = READ_ROW5(); + t6 = READ_ROW6(); + t7 = READ_ROW7(); + t8 = MUL(0x02, t0) ^ MUL(0x04, t1) ^ MUL(0x02, t2) ^ MUL(0x0b, t3) ^ + MUL(0x02, t4) ^ MUL(0x08, t5) ^ MUL(0x05, t6) ^ MUL(0x06, t7); + WRITE_ROW(0, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x09, t1) ^ MUL(0x08, t2) ^ MUL(0x0d, t3) ^ + MUL(0x07, t4) ^ MUL(0x07, t5) ^ MUL(0x05, t6) ^ MUL(0x02, t7); + WRITE_ROW(1, t8); + t8 = MUL(0x04, t0) ^ MUL(0x04, t1) ^ MUL(0x0d, t2) ^ MUL(0x0d, t3) ^ + MUL(0x09, t4) ^ MUL(0x04, t5) ^ MUL(0x0d, t6) ^ MUL(0x09, t7); + WRITE_ROW(2, t8); + t8 = MUL(0x01, t0) ^ MUL(0x06, t1) ^ MUL(0x05, t2) ^ MUL(0x01, t3) ^ + MUL(0x0c, t4) ^ MUL(0x0d, t5) ^ MUL(0x0f, t6) ^ MUL(0x0e, t7); + WRITE_ROW(3, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x0c, t1) ^ MUL(0x09, t2) ^ MUL(0x0d, t3) ^ + MUL(0x0e, t4) ^ MUL(0x05, t5) ^ MUL(0x0e, t6) ^ MUL(0x0d, t7); + WRITE_ROW(4, t8); + t8 = MUL(0x09, t0) ^ MUL(0x0e, t1) ^ MUL(0x05, t2) ^ MUL(0x0f, t3) ^ + MUL(0x04, t4) ^ MUL(0x0c, t5) ^ MUL(0x09, t6) ^ MUL(0x06, t7); + WRITE_ROW(5, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x02, t1) ^ MUL(0x02, t2) ^ MUL(0x0a, t3) ^ + MUL(0x03, t4) ^ MUL(0x01, t5) ^ MUL(0x01, t6) ^ MUL(0x0e, t7); + WRITE_ROW(6, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x01, t1) ^ MUL(0x0d, t2) ^ MUL(0x0a, t3) ^ + MUL(0x05, t4) ^ MUL(0x0a, t5) ^ MUL(0x02, t6) ^ MUL(0x03, t7); + WRITE_ROW(7, t8); + } + + /* Convert back from bit-sliced form to regular form */ + photon256_from_sliced(state, S.bytes); +} diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.h b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.h new file mode 100644 index 0000000..ce8729a --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-photon256.h @@ -0,0 +1,54 @@ +/* + * 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_PHOTON256_H +#define LW_INTERNAL_PHOTON256_H + +/** + * \file internal-photon256.h + * \brief Internal implementation of the PHOTON-256 permutation. + * + * Warning: The current implementation of PHOTON-256 is constant-time + * but not constant-cache. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the PHOTON-256 permutation state in bytes. + */ +#define PHOTON256_STATE_SIZE 32 + +/** + * \brief Permutes the PHOTON-256 state. + * + * \param state The state to be permuted. + */ +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-util.h b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.c b/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.c new file mode 100644 index 0000000..641e117 --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.c @@ -0,0 +1,384 @@ +/* + * 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 "orange.h" +#include "internal-photon256.h" +#include "internal-util.h" +#include + +aead_cipher_t const orange_zest_cipher = { + "ORANGE-Zest", + ORANGE_ZEST_KEY_SIZE, + ORANGE_ZEST_NONCE_SIZE, + ORANGE_ZEST_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + orange_zest_aead_encrypt, + orange_zest_aead_decrypt +}; + +aead_hash_algorithm_t const orangish_hash_algorithm = { + "ORANGISH", + sizeof(int), + ORANGISH_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + orangish_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 Doubles a block in the GF(128) field a number of times. + * + * \param block The block to be doubled. + * \param value The number of times to double the block. + */ +static void orange_block_double(unsigned char block[16], unsigned char value) +{ + unsigned index; + unsigned char mask; + while (value > 0) { + mask = (unsigned char)(((signed char)(block[15])) >> 7); + for (index = 15; index > 0; --index) + block[index] = (block[index] << 1) | (block[index - 1] >> 7); + block[0] = (block[0] << 1) ^ (mask & 0x87); + --value; + } +} + +/** + * \brief Rotates a block left by 1 bit. + * + * \param out The output block to be set to the rotated version. + * \param in The input block to be rotated, must not overlap with \a out. + */ +static void orange_block_rotate + (unsigned char out[16], const unsigned char in[16]) +{ + unsigned index; + for (index = 15; index > 0; --index) + out[index] = (in[index] << 1) | (in[index - 1] >> 7); + out[0] = (in[0] << 1) | (in[15] >> 7); +} + +/** + * \brief Hash input data with ORANGE. + * + * \param state PHOTON-256 permutation state. + * \param data Points to the data to be hashed. + * \param len Length of the data to be hashed, must not be zero. + * \param domain0 Domain separation value for full last block. + * \param domain1 Domain separation value for partial last block. + */ +static void orange_process_hash + (unsigned char state[PHOTON256_STATE_SIZE], + const unsigned char *data, unsigned long long len, + unsigned char domain0, unsigned char domain1) +{ + unsigned temp; + while (len > PHOTON256_STATE_SIZE) { + photon256_permute(state); + lw_xor_block(state, data, PHOTON256_STATE_SIZE); + data += PHOTON256_STATE_SIZE; + len -= PHOTON256_STATE_SIZE; + } + photon256_permute(state); + temp = (unsigned)len; + if (temp < PHOTON256_STATE_SIZE) { + orange_block_double(state + 16, domain1); + state[temp] ^= 0x01; /* padding */ + } else { + orange_block_double(state + 16, domain0); + } + lw_xor_block(state, data, temp); +} + +/** + * \brief Applies the rho function to the ORANGE state. + * + * \param KS Output keystream to use to encrypt the plaintext or to + * decrypt the ciphertext. + * \param S Rolling key state. + * \param state Rolling PHOTON-256 permutation state. + */ +static void orange_rho + (unsigned char KS[32], unsigned char S[16], const unsigned char state[32]) +{ + orange_block_double(S, 1); + orange_block_rotate(KS, state); + lw_xor_block_2_src(KS + 16, state + 16, S, 16); + memcpy(S, state + 16, 16); +} + +/** + * \brief Encrypts plaintext with ORANGE. + * + * \param state PHOTON-256 permutation state. + * \param k Points to the key for the cipher. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param len Length of the plaintext in bytes, must not be zero. + */ +static void orange_encrypt + (unsigned char state[PHOTON256_STATE_SIZE], const unsigned char *k, + unsigned char *c, const unsigned char *m, unsigned long long len) +{ + unsigned char S[ORANGE_ZEST_KEY_SIZE]; + unsigned char KS[PHOTON256_STATE_SIZE]; + unsigned temp; + memcpy(S, k, ORANGE_ZEST_KEY_SIZE); + while (len > PHOTON256_STATE_SIZE) { + photon256_permute(state); + orange_rho(KS, S, state); + lw_xor_block_2_src(c, m, KS, PHOTON256_STATE_SIZE); + lw_xor_block(state, c, PHOTON256_STATE_SIZE); + c += PHOTON256_STATE_SIZE; + m += PHOTON256_STATE_SIZE; + len -= PHOTON256_STATE_SIZE; + } + photon256_permute(state); + temp = (unsigned)len; + if (temp < PHOTON256_STATE_SIZE) { + orange_block_double(state + 16, 2); + orange_rho(KS, S, state); + lw_xor_block_2_src(c, m, KS, temp); + lw_xor_block(state, c, temp); + state[temp] ^= 0x01; /* padding */ + } else { + orange_block_double(state + 16, 1); + orange_rho(KS, S, state); + lw_xor_block_2_src(c, m, KS, PHOTON256_STATE_SIZE); + lw_xor_block(state, c, PHOTON256_STATE_SIZE); + } +} + +/** + * \brief Decrypts ciphertext with ORANGE. + * + * \param state PHOTON-256 permutation state. + * \param k Points to the key for the cipher. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param len Length of the plaintext in bytes, must not be zero. + */ +static void orange_decrypt + (unsigned char state[PHOTON256_STATE_SIZE], const unsigned char *k, + unsigned char *m, const unsigned char *c, unsigned long long len) +{ + unsigned char S[ORANGE_ZEST_KEY_SIZE]; + unsigned char KS[PHOTON256_STATE_SIZE]; + unsigned temp; + memcpy(S, k, ORANGE_ZEST_KEY_SIZE); + while (len > PHOTON256_STATE_SIZE) { + photon256_permute(state); + orange_rho(KS, S, state); + lw_xor_block(state, c, PHOTON256_STATE_SIZE); + lw_xor_block_2_src(m, c, KS, PHOTON256_STATE_SIZE); + c += PHOTON256_STATE_SIZE; + m += PHOTON256_STATE_SIZE; + len -= PHOTON256_STATE_SIZE; + } + photon256_permute(state); + temp = (unsigned)len; + if (temp < PHOTON256_STATE_SIZE) { + orange_block_double(state + 16, 2); + orange_rho(KS, S, state); + lw_xor_block(state, c, temp); + lw_xor_block_2_src(m, c, KS, temp); + state[temp] ^= 0x01; /* padding */ + } else { + orange_block_double(state + 16, 1); + orange_rho(KS, S, state); + lw_xor_block(state, c, PHOTON256_STATE_SIZE); + lw_xor_block_2_src(m, c, KS, PHOTON256_STATE_SIZE); + } +} + +/** + * \brief Generates the authentication tag for ORANGE-Zest. + * + * \param state PHOTON-256 permutation state. + * + * The tag will be left in the leading bytes of the state on exit. + */ +static void orange_generate_tag(unsigned char state[PHOTON256_STATE_SIZE]) +{ + /* Swap the two halves of the state and run the permutation again */ + unsigned posn; + for (posn = 0; posn < (PHOTON256_STATE_SIZE / 2); ++posn) { + unsigned char temp = state[posn]; + state[posn] = state[posn + (PHOTON256_STATE_SIZE / 2)]; + state[posn + (PHOTON256_STATE_SIZE / 2)] = temp; + } + photon256_permute(state); +} + +int orange_zest_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ORANGE_ZEST_TAG_SIZE; + + /* Initialize the PHOTON-256 state with the nonce and key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Handle the associated data and message payload */ + if (adlen == 0) { + if (mlen == 0) { + state[16] ^= 2; /* domain separation */ + photon256_permute(state); + memcpy(c + mlen, state, ORANGE_ZEST_TAG_SIZE); + return 0; + } else { + state[16] ^= 1; /* domain separation */ + orange_encrypt(state, k, c, m, mlen); + } + } else { + orange_process_hash(state, ad, adlen, 1, 2); + if (mlen != 0) + orange_encrypt(state, k, c, m, mlen); + } + + /* Generate the authentication tag */ + orange_generate_tag(state); + memcpy(c + mlen, state, ORANGE_ZEST_TAG_SIZE); + return 0; +} + +int orange_zest_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ORANGE_ZEST_TAG_SIZE) + return -1; + *mlen = clen - ORANGE_ZEST_TAG_SIZE; + + /* Initialize the PHOTON-256 state with the nonce and key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Handle the associated data and message payload */ + clen -= ORANGE_ZEST_TAG_SIZE; + if (adlen == 0) { + if (clen == 0) { + state[16] ^= 2; /* domain separation */ + photon256_permute(state); + return aead_check_tag(m, 0, state, c, ORANGE_ZEST_TAG_SIZE); + } else { + state[16] ^= 1; /* domain separation */ + orange_decrypt(state, k, m, c, clen); + } + } else { + orange_process_hash(state, ad, adlen, 1, 2); + if (clen != 0) + orange_decrypt(state, k, m, c, clen); + } + + /* Check the authentication tag */ + orange_generate_tag(state); + return aead_check_tag(m, clen, state, c + clen, ORANGE_ZEST_TAG_SIZE); +} + +/** + * \brief Rate of absorbing data into the ORANGISH hash state. + */ +#define ORANGISH_RATE 16 + +int orangish_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + unsigned temp; + memset(state, 0, sizeof(state)); + if (inlen == 0) { + /* No absorption necessary for a zero-length input */ + } else if (inlen < ORANGISH_RATE) { + /* Single partial block */ + temp = (unsigned)inlen; + memcpy(state, in, temp); + state[temp] ^= 0x01; /* padding */ + photon256_permute(state); + lw_xor_block(state + 16, in, temp); + state[16 + temp] ^= 0x01; /* padding */ + state[0] ^= 0x02; /* domain separation */ + } else if (inlen == ORANGISH_RATE) { + /* Single full block */ + memcpy(state, in, ORANGISH_RATE); + photon256_permute(state); + lw_xor_block(state + 16, in, ORANGISH_RATE); + state[0] ^= 0x01; /* domain separation */ + } else { + /* Process double blocks until we run out */ + memcpy(state, in, ORANGISH_RATE); + photon256_permute(state); + lw_xor_block(state + 16, in, ORANGISH_RATE); + in += ORANGISH_RATE; + inlen -= ORANGISH_RATE; + while (inlen > ORANGISH_RATE) { + lw_xor_block(state, in, ORANGISH_RATE); + photon256_permute(state); + lw_xor_block(state + 16, in, ORANGISH_RATE); + in += ORANGISH_RATE; + inlen -= ORANGISH_RATE; + } + temp = (unsigned)inlen; + if (temp < ORANGISH_RATE) { + /* Last double block is partial */ + lw_xor_block(state, in, temp); + state[temp] ^= 0x01; /* padding */ + photon256_permute(state); + lw_xor_block(state + 16, in, temp); + state[16 + temp] ^= 0x01; /* padding */ + state[0] ^= 0x02; /* domain separation */ + } else { + /* Last double block is full */ + lw_xor_block(state, in, ORANGISH_RATE); + photon256_permute(state); + lw_xor_block(state + 16, in, ORANGISH_RATE); + state[0] ^= 0x01; /* domain separation */ + } + } + photon256_permute(state); + memcpy(out, state, 16); + photon256_permute(state); + memcpy(out + 16, state, 16); + return 0; +} diff --git a/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.h b/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.h new file mode 100644 index 0000000..de5b00c --- /dev/null +++ b/orange/Implementations/crypto_aead/orangezestv1/rhys/orange.h @@ -0,0 +1,153 @@ +/* + * 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_ORANGE_H +#define LWCRYPTO_ORANGE_H + +#include "aead-common.h" + +/** + * \file orange.h + * \brief ORANGE authenticated encryption algorithm. + * + * ORANGE is a family of algorithms built around the PHOTON-256 permutation. + * There are two members of the family at present: + * + * \li ORANGE-Zest is an authenticated encryption algorithm with a 128-bit + * key, a 128-bit nonce, and a 128-bit tag. + * \li ORANGISH is a hash algorithm with a 256-bit output. + * + * References: https://www.isical.ac.in/~lightweight/Orange/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for ORANGE-Zest. + */ +#define ORANGE_ZEST_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for ORANGE-Zest. + */ +#define ORANGE_ZEST_TAG_SIZE 16 + +/** + * \brief Size of the nonce for ORANGE-Zest. + */ +#define ORANGE_ZEST_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for the ORANGISH hash algorithm. + */ +#define ORANGISH_HASH_SIZE 32 + +/** + * \brief Meta-information block for the ORANGE-Zest cipher. + */ +extern aead_cipher_t const orange_zest_cipher; + +/** + * \brief Meta-information block for the ORANGISH hash algorithm. + */ +extern aead_hash_algorithm_t const orangish_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with ORANGE-Zest. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa orange_zest_aead_decrypt() + */ +int orange_zest_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); + +/** + * \brief Decrypts and authenticates a packet with ORANGE-Zest. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa orange_zest_aead_encrypt() + */ +int orange_zest_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); + +/** + * \brief Hashes a block of input data with ORANGISH to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ORANGISH_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 orangish_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.c b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.h b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/api.h b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/api.h new file mode 100644 index 0000000..bd8cdcb --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 8 +#define CRYPTO_ABYTES 12 +#define CRYPTO_NOOVERLAP 1 diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/encrypt.c b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/encrypt.c new file mode 100644 index 0000000..681e037 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "oribatida.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 oribatida_192_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 oribatida_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.c b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.c new file mode 100644 index 0000000..4ca50d0 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.c @@ -0,0 +1,168 @@ +/* + * 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 "internal-simp.h" + +/** + * \brief Number of rounds for the inner block cipher within SimP-256. + */ +#define SIMP_256_ROUNDS 34 + +/** + * \brief Number of rounds for the inner block cipher within SimP-192. + */ +#define SIMP_192_ROUNDS 26 + +/** + * \brief Round constants for each of the rounds in SimP-256 or SimP-192. + * + * Bit i is the round constant for round i, repeated every 62 rounds. + */ +#define SIMP_RC 0x3369F885192C0EF5ULL + +void simp_256_permute(unsigned char state[SIMP_256_STATE_SIZE], unsigned steps) +{ + uint64_t z = SIMP_RC; + uint64_t x0, x1, x2, x3, t0, t1; + unsigned round; + + /* Load the state into local variables */ + x0 = be_load_word64(state); + x1 = be_load_word64(state + 8); + x2 = be_load_word64(state + 16); + x3 = be_load_word64(state + 24); + + /* Perform all steps */ + for (; steps > 0; --steps) { + /* Perform all rounds for this step, two at a time */ + for (round = 0; round < (SIMP_256_ROUNDS / 2); ++round) { + t1 = x3 ^ (leftRotate1_64(x2) & leftRotate8_64(x2)) ^ + leftRotate2_64(x2) ^ x1; + t0 = x1 ^ rightRotate3_64(x0) ^ rightRotate4_64(x0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + x2 = x2 ^ (leftRotate1_64(t1) & leftRotate8_64(t1)) ^ + leftRotate2_64(t1) ^ x0; + x0 = x0 ^ rightRotate3_64(t0) ^ rightRotate4_64(t0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + x1 = t0; + x3 = t1; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + } + + /* Swap the words of the state for all steps except the last */ + if (steps > 1) { + t0 = x0; + t1 = x1; + x0 = x2; + x1 = x3; + x2 = t0; + x3 = t1; + } + } + + /* Write the local variables back to the state */ + be_store_word64(state, x0); + be_store_word64(state + 8, x1); + be_store_word64(state + 16, x2); + be_store_word64(state + 24, x3); +} + +/* Load a big-endian 48-bit word from a byte buffer */ +#define be_load_word48(ptr) \ + ((((uint64_t)((ptr)[0])) << 40) | \ + (((uint64_t)((ptr)[1])) << 32) | \ + (((uint64_t)((ptr)[2])) << 24) | \ + (((uint64_t)((ptr)[3])) << 16) | \ + (((uint64_t)((ptr)[4])) << 8) | \ + ((uint64_t)((ptr)[5]))) + +/* Store a big-endian 48-bit word into a byte buffer */ +#define be_store_word48(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 40); \ + (ptr)[1] = (uint8_t)(_x >> 32); \ + (ptr)[2] = (uint8_t)(_x >> 24); \ + (ptr)[3] = (uint8_t)(_x >> 16); \ + (ptr)[4] = (uint8_t)(_x >> 8); \ + (ptr)[5] = (uint8_t)_x; \ + } while (0) + +/* 48-bit rotations with the high bits set to garbage - truncated later */ +#define rightRotate3_48(x) (((x) >> 3) | ((x) << 45)) +#define rightRotate4_48(x) (((x) >> 4) | ((x) << 44)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 47)) +#define leftRotate2_48(x) (((x) << 2) | ((x) >> 46)) +#define leftRotate8_48(x) (((x) << 8) | ((x) >> 40)) + +void simp_192_permute(unsigned char state[SIMP_192_STATE_SIZE], unsigned steps) +{ + uint64_t z = SIMP_RC; + uint64_t x0, x1, x2, x3, t0, t1; + unsigned round; + + /* Load the state into local variables */ + x0 = be_load_word48(state); + x1 = be_load_word48(state + 6); + x2 = be_load_word48(state + 12); + x3 = be_load_word48(state + 18); + + /* Perform all steps */ + for (; steps > 0; --steps) { + /* Perform all rounds for this step, two at a time */ + for (round = 0; round < (SIMP_192_ROUNDS / 2); ++round) { + t1 = x3 ^ (leftRotate1_48(x2) & leftRotate8_48(x2)) ^ + leftRotate2_48(x2) ^ x1; + t0 = x1 ^ rightRotate3_48(x0) ^ rightRotate4_48(x0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + t0 &= 0x0000FFFFFFFFFFFFULL; /* Truncate back to 48 bits */ + t1 &= 0x0000FFFFFFFFFFFFULL; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + x2 = x2 ^ (leftRotate1_48(t1) & leftRotate8_48(t1)) ^ + leftRotate2_48(t1) ^ x0; + x0 = x0 ^ rightRotate3_48(t0) ^ rightRotate4_48(t0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + x0 &= 0x0000FFFFFFFFFFFFULL; + x2 &= 0x0000FFFFFFFFFFFFULL; + x1 = t0; + x3 = t1; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + } + + /* Swap the words of the state for all steps except the last */ + if (steps > 1) { + t0 = x0; + t1 = x1; + x0 = x2; + x1 = x3; + x2 = t0; + x3 = t1; + } + } + + /* Write the local variables back to the state */ + be_store_word48(state, x0); + be_store_word48(state + 6, x1); + be_store_word48(state + 12, x2); + be_store_word48(state + 18, x3); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.h b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.h new file mode 100644 index 0000000..3a95e80 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-simp.h @@ -0,0 +1,74 @@ +/* + * 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_SIMP_H +#define LW_INTERNAL_SIMP_H + +#include "internal-util.h" + +/** + * \file internal-simp.h + * \brief SimP permutation family. + * + * SimP-256 and SimP-192 are used by the Oribatida submission to + * round 2 of the NIST Lightweight Cryptography Competition. + * The permutations are built around reduced-round variants of the + * Simon-128-128 and Simon-96-96 block ciphers. + * + * References: https://www.isical.ac.in/~lightweight/oribatida/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief State size of the SimP-256 permutation. + */ +#define SIMP_256_STATE_SIZE 32 + +/** + * \brief State size of the SimP-192 permutation. + */ +#define SIMP_192_STATE_SIZE 24 + +/** + * \brief Permutes a state with SimP-256. + * + * \param state State to be permuted. + * \param steps Number of steps to perform (usually 2 or 4). + */ +void simp_256_permute(unsigned char state[SIMP_256_STATE_SIZE], unsigned steps); + +/** + * \brief Permutes a state with SimP-192. + * + * \param state State to be permuted. + * \param steps Number of steps to perform (usually 2 or 4). + */ +void simp_192_permute(unsigned char state[SIMP_192_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-util.h b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.c b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.c new file mode 100644 index 0000000..55a3914 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.c @@ -0,0 +1,480 @@ +/* + * 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 "oribatida.h" +#include "internal-simp.h" +#include + +/** + * \brief Rate for processing data for the Oribatida-256-64 state. + */ +#define ORIBATIDA_256_RATE 16 + +/** + * \brief Size of the masking value for Oribatida-256-64. + */ +#define ORIBATIDA_256_MASK_SIZE 8 + +/** + * \brief Rate for processing data for the Oribatida-192-96 state. + */ +#define ORIBATIDA_192_RATE 12 + +/** + * \brief Size of the masking value for Oribatida-192-96. + */ +#define ORIBATIDA_192_MASK_SIZE 12 + +aead_cipher_t const oribatida_256_cipher = { + "Oribatida-256-64", + ORIBATIDA_256_KEY_SIZE, + ORIBATIDA_256_NONCE_SIZE, + ORIBATIDA_256_TAG_SIZE, + AEAD_FLAG_NONE, + oribatida_256_aead_encrypt, + oribatida_256_aead_decrypt +}; + +aead_cipher_t const oribatida_192_cipher = { + "Oribatida-192-96", + ORIBATIDA_192_KEY_SIZE, + ORIBATIDA_192_NONCE_SIZE, + ORIBATIDA_192_TAG_SIZE, + AEAD_FLAG_NONE, + oribatida_192_aead_encrypt, + oribatida_192_aead_decrypt +}; + +/* Definitions for domain separation values */ +#define ORIBATIDA_NUM_DOMAINS 3 +#define ORIBATIDA_DOMAIN_NONCE 0 +#define ORIBATIDA_DOMAIN_AD 1 +#define ORIBATIDA_DOMAIN_MSG 2 + +/** + * \brief Gets the domain separation values to use for different phases + * of the Oribatida encryption process. + * + * \param domains Returns the domain separation values to use. + * \param adlen Length of the associated data. + * \param mlen Length of the plaintext message. + * \param rate Rate of processing message blocks, 12 or 16. + */ +static void oribatida_get_domains + (unsigned char domains[ORIBATIDA_NUM_DOMAINS], + unsigned long long adlen, unsigned long long mlen, unsigned rate) +{ + /* Domain separation value for the nonce */ + if (adlen == 0 && mlen == 0) { + domains[ORIBATIDA_DOMAIN_NONCE] = 9; + } else { + domains[ORIBATIDA_DOMAIN_NONCE] = 5; + } + + /* Domain separation value for associated data processing */ + if (mlen == 0) { + if ((adlen % rate) == 0) + domains[ORIBATIDA_DOMAIN_AD] = 12; + else + domains[ORIBATIDA_DOMAIN_AD] = 14; + } else { + if ((adlen % rate) == 0) + domains[ORIBATIDA_DOMAIN_AD] = 4; + else + domains[ORIBATIDA_DOMAIN_AD] = 6; + } + + /* Domain separation value for message processing */ + if ((mlen % rate) == 0) { + domains[ORIBATIDA_DOMAIN_MSG] = 13; + } else { + domains[ORIBATIDA_DOMAIN_MSG] = 15; + } +} + +/** + * \brief Initializes the Oribatida-256-64 state. + * + * \param state Oribatida-256-64 permutation state. + * \param mask Oribatida-256-64 masking state. + * \param domains Precomputed domain separation values. + * \param k Points to the key. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void oribatida_256_init + (unsigned char state[SIMP_256_STATE_SIZE], + unsigned char mask[ORIBATIDA_256_MASK_SIZE], + const unsigned char domains[ORIBATIDA_NUM_DOMAINS], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state with the key and nonce */ + memcpy(state, npub, ORIBATIDA_256_NONCE_SIZE); + memcpy(state + ORIBATIDA_256_NONCE_SIZE, k, ORIBATIDA_256_KEY_SIZE); + + /* Use the current state as the mask for zero-length associated data */ + if (adlen == 0) { + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + } + + /* Add the domain separation value for the nonce */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_NONCE]; + + /* Run the permutation for the first time */ + simp_256_permute(state, 4); + + /* If there is no associated data, then we are done */ + if (adlen == 0) + return; + + /* Use the current state as the mask for non-zero length associated data */ + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + + /* Process all associated data blocks except the last */ + while (adlen > ORIBATIDA_256_RATE) { + lw_xor_block(state, ad, ORIBATIDA_256_RATE); + simp_256_permute(state, 2); + ad += ORIBATIDA_256_RATE; + adlen -= ORIBATIDA_256_RATE; + } + + /* Process the final associated data block */ + temp = (unsigned)adlen; + if (temp == ORIBATIDA_256_RATE) { + lw_xor_block(state, ad, ORIBATIDA_256_RATE); + } else { + lw_xor_block(state, ad, temp); + state[temp] ^= 0x80; /* padding */ + } + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_AD]; + simp_256_permute(state, 4); +} + +/** + * \brief Initializes the Oribatida-192-96 state. + * + * \param state Oribatida-192-96 permutation state. + * \param mask Oribatida-192-96 masking state. + * \param domains Precomputed domain separation values. + * \param k Points to the key. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void oribatida_192_init + (unsigned char state[SIMP_192_STATE_SIZE], + unsigned char mask[ORIBATIDA_192_MASK_SIZE], + const unsigned char domains[ORIBATIDA_NUM_DOMAINS], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state with the key and nonce */ + memcpy(state, npub, ORIBATIDA_192_NONCE_SIZE); + memcpy(state + ORIBATIDA_192_NONCE_SIZE, k, ORIBATIDA_256_KEY_SIZE); + + /* Use the current state as the mask for zero-length associated data */ + if (adlen == 0) { + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + } + + /* Add the domain separation value for the nonce */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_NONCE]; + + /* Run the permutation for the first time */ + simp_192_permute(state, 4); + + /* If there is no associated data, then we are done */ + if (adlen == 0) + return; + + /* Use the current state as the mask for non-zero length associated data */ + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + + /* Process all associated data blocks except the last */ + while (adlen > ORIBATIDA_192_RATE) { + lw_xor_block(state, ad, ORIBATIDA_192_RATE); + simp_192_permute(state, 2); + ad += ORIBATIDA_192_RATE; + adlen -= ORIBATIDA_192_RATE; + } + + /* Process the final associated data block */ + temp = (unsigned)adlen; + if (temp == ORIBATIDA_192_RATE) { + lw_xor_block(state, ad, ORIBATIDA_192_RATE); + } else { + lw_xor_block(state, ad, temp); + state[temp] ^= 0x80; /* padding */ + } + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_AD]; + simp_192_permute(state, 4); +} + +int oribatida_256_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) +{ + unsigned char state[SIMP_256_STATE_SIZE]; + unsigned char mask[ORIBATIDA_256_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ORIBATIDA_256_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + oribatida_get_domains(domains, adlen, mlen, ORIBATIDA_256_RATE); + oribatida_256_init(state, mask, domains, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen > ORIBATIDA_256_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_256_RATE); + lw_xor_block(c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + simp_256_permute(state, 4); + c += ORIBATIDA_256_RATE; + m += ORIBATIDA_256_RATE; + mlen -= ORIBATIDA_256_RATE; + } + if (mlen == ORIBATIDA_256_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_256_RATE); + lw_xor_block(c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } else if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state, m, temp); + if (temp > (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)) { + lw_xor_block + (c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, mask, + temp - (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)); + } + state[temp] ^= 0x80; /* padding */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } + + /* Generate the authentication tag */ + memcpy(c + mlen, state, ORIBATIDA_256_TAG_SIZE); + return 0; +} + +int oribatida_256_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) +{ + unsigned char state[SIMP_256_STATE_SIZE]; + unsigned char mask[ORIBATIDA_256_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + unsigned char block[ORIBATIDA_256_RATE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ORIBATIDA_256_TAG_SIZE) + return -1; + *mlen = clen - ORIBATIDA_256_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + clen -= ORIBATIDA_256_TAG_SIZE; + oribatida_get_domains(domains, adlen, clen, ORIBATIDA_256_RATE); + oribatida_256_init(state, mask, domains, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + while (clen > ORIBATIDA_256_RATE) { + memcpy(block, c, ORIBATIDA_256_RATE); + lw_xor_block(block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_256_RATE); + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + simp_256_permute(state, 4); + c += ORIBATIDA_256_RATE; + m += ORIBATIDA_256_RATE; + clen -= ORIBATIDA_256_RATE; + } + if (clen == ORIBATIDA_256_RATE) { + memcpy(block, c, ORIBATIDA_256_RATE); + lw_xor_block(block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_256_RATE); + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } else if (clen > 0) { + unsigned temp = (unsigned)clen; + memcpy(block, c, temp); + if (temp > (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)) { + lw_xor_block + (block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, mask, + temp - (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)); + } + lw_xor_block_swap(m, state, block, temp); + state[temp] ^= 0x80; /* padding */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } + c += clen; + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state, c, ORIBATIDA_256_TAG_SIZE); +} + +int oribatida_192_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) +{ + unsigned char state[SIMP_192_STATE_SIZE]; + unsigned char mask[ORIBATIDA_192_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ORIBATIDA_192_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + oribatida_get_domains(domains, adlen, mlen, ORIBATIDA_192_RATE); + oribatida_192_init(state, mask, domains, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen > ORIBATIDA_192_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_192_RATE); + lw_xor_block(c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + simp_192_permute(state, 4); + c += ORIBATIDA_192_RATE; + m += ORIBATIDA_192_RATE; + mlen -= ORIBATIDA_192_RATE; + } + if (mlen == ORIBATIDA_192_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_192_RATE); + lw_xor_block(c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } else if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state, m, temp); + if (temp > (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)) { + lw_xor_block + (c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, mask, + temp - (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)); + } + state[temp] ^= 0x80; /* padding */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } + + /* Generate the authentication tag */ + memcpy(c + mlen, state, ORIBATIDA_192_TAG_SIZE); + return 0; +} + +int oribatida_192_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) +{ + unsigned char state[SIMP_192_STATE_SIZE]; + unsigned char mask[ORIBATIDA_192_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + unsigned char block[ORIBATIDA_192_RATE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ORIBATIDA_192_TAG_SIZE) + return -1; + *mlen = clen - ORIBATIDA_192_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + clen -= ORIBATIDA_192_TAG_SIZE; + oribatida_get_domains(domains, adlen, clen, ORIBATIDA_192_RATE); + oribatida_192_init(state, mask, domains, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + while (clen > ORIBATIDA_192_RATE) { + memcpy(block, c, ORIBATIDA_192_RATE); + lw_xor_block(block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_192_RATE); + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + simp_192_permute(state, 4); + c += ORIBATIDA_192_RATE; + m += ORIBATIDA_192_RATE; + clen -= ORIBATIDA_192_RATE; + } + if (clen == ORIBATIDA_192_RATE) { + memcpy(block, c, ORIBATIDA_192_RATE); + lw_xor_block(block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_192_RATE); + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } else if (clen > 0) { + unsigned temp = (unsigned)clen; + memcpy(block, c, temp); + if (temp > (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)) { + lw_xor_block + (block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, mask, + temp - (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)); + } + lw_xor_block_swap(m, state, block, temp); + state[temp] ^= 0x80; /* padding */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } + c += clen; + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state, c, ORIBATIDA_192_TAG_SIZE); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.h b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.h new file mode 100644 index 0000000..dbc374b --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida192v12/rhys/oribatida.h @@ -0,0 +1,212 @@ +/* + * 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_ORIBATIDA_H +#define LWCRYPTO_ORIBATIDA_H + +#include "aead-common.h" + +/** + * \file oribatida.h + * \brief Oribatida authenticated encryption algorithm. + * + * Oribatida is a family of authenticated encryption algorithms based on the + * SimP-256 and SimP-192 permutations which are built around reduced-round + * variants of the Simon-128-128 and Simon-96-96 block ciphers. + * There are two algorithms in the family: + * + * \li Oribatida-256-64 with a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * built around the SimP-256 permutation. This is the primary member of + * the family. + * \li Oribatida-192-96 with a 128-bit key, a 64-bit nonce, and a 96-bit tag, + * built around the SimP-192 permutation. + * + * References: https://www.isical.ac.in/~lightweight/oribatida/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Oribatida-256-64. + */ +#define ORIBATIDA_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Oribatida-256-64. + */ +#define ORIBATIDA_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Oribatida-256-64. + */ +#define ORIBATIDA_256_NONCE_SIZE 16 + +/** + * \brief Size of the key for Oribatida-192-96. + */ +#define ORIBATIDA_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Oribatida-192-96. + */ +#define ORIBATIDA_192_TAG_SIZE 12 + +/** + * \brief Size of the nonce for Oribatida-192-96. + */ +#define ORIBATIDA_192_NONCE_SIZE 8 + +/** + * \brief Meta-information block for the Oribatida-256-64 cipher. + */ +extern aead_cipher_t const oribatida_256_cipher; + +/** + * \brief Meta-information block for the Oribatida-192-96 cipher. + */ +extern aead_cipher_t const oribatida_192_cipher; + +/** + * \brief Encrypts and authenticates a packet with Oribatida-256-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa oribatida_256_aead_decrypt() + */ +int oribatida_256_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); + +/** + * \brief Decrypts and authenticates a packet with Oribatida-256-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa oribatida_256_aead_encrypt() + */ +int oribatida_256_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); + +/** + * \brief Encrypts and authenticates a packet with Oribatida-192-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa oribatida_192_aead_decrypt() + */ +int oribatida_192_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); + +/** + * \brief Decrypts and authenticates a packet with Oribatida-192-96. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa oribatida_192_aead_encrypt() + */ +int oribatida_192_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.c b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.h b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/api.h b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/encrypt.c b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/encrypt.c new file mode 100644 index 0000000..fd7d71e --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "oribatida.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 oribatida_256_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 oribatida_256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.c b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.c new file mode 100644 index 0000000..4ca50d0 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.c @@ -0,0 +1,168 @@ +/* + * 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 "internal-simp.h" + +/** + * \brief Number of rounds for the inner block cipher within SimP-256. + */ +#define SIMP_256_ROUNDS 34 + +/** + * \brief Number of rounds for the inner block cipher within SimP-192. + */ +#define SIMP_192_ROUNDS 26 + +/** + * \brief Round constants for each of the rounds in SimP-256 or SimP-192. + * + * Bit i is the round constant for round i, repeated every 62 rounds. + */ +#define SIMP_RC 0x3369F885192C0EF5ULL + +void simp_256_permute(unsigned char state[SIMP_256_STATE_SIZE], unsigned steps) +{ + uint64_t z = SIMP_RC; + uint64_t x0, x1, x2, x3, t0, t1; + unsigned round; + + /* Load the state into local variables */ + x0 = be_load_word64(state); + x1 = be_load_word64(state + 8); + x2 = be_load_word64(state + 16); + x3 = be_load_word64(state + 24); + + /* Perform all steps */ + for (; steps > 0; --steps) { + /* Perform all rounds for this step, two at a time */ + for (round = 0; round < (SIMP_256_ROUNDS / 2); ++round) { + t1 = x3 ^ (leftRotate1_64(x2) & leftRotate8_64(x2)) ^ + leftRotate2_64(x2) ^ x1; + t0 = x1 ^ rightRotate3_64(x0) ^ rightRotate4_64(x0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + x2 = x2 ^ (leftRotate1_64(t1) & leftRotate8_64(t1)) ^ + leftRotate2_64(t1) ^ x0; + x0 = x0 ^ rightRotate3_64(t0) ^ rightRotate4_64(t0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + x1 = t0; + x3 = t1; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + } + + /* Swap the words of the state for all steps except the last */ + if (steps > 1) { + t0 = x0; + t1 = x1; + x0 = x2; + x1 = x3; + x2 = t0; + x3 = t1; + } + } + + /* Write the local variables back to the state */ + be_store_word64(state, x0); + be_store_word64(state + 8, x1); + be_store_word64(state + 16, x2); + be_store_word64(state + 24, x3); +} + +/* Load a big-endian 48-bit word from a byte buffer */ +#define be_load_word48(ptr) \ + ((((uint64_t)((ptr)[0])) << 40) | \ + (((uint64_t)((ptr)[1])) << 32) | \ + (((uint64_t)((ptr)[2])) << 24) | \ + (((uint64_t)((ptr)[3])) << 16) | \ + (((uint64_t)((ptr)[4])) << 8) | \ + ((uint64_t)((ptr)[5]))) + +/* Store a big-endian 48-bit word into a byte buffer */ +#define be_store_word48(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 40); \ + (ptr)[1] = (uint8_t)(_x >> 32); \ + (ptr)[2] = (uint8_t)(_x >> 24); \ + (ptr)[3] = (uint8_t)(_x >> 16); \ + (ptr)[4] = (uint8_t)(_x >> 8); \ + (ptr)[5] = (uint8_t)_x; \ + } while (0) + +/* 48-bit rotations with the high bits set to garbage - truncated later */ +#define rightRotate3_48(x) (((x) >> 3) | ((x) << 45)) +#define rightRotate4_48(x) (((x) >> 4) | ((x) << 44)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 47)) +#define leftRotate2_48(x) (((x) << 2) | ((x) >> 46)) +#define leftRotate8_48(x) (((x) << 8) | ((x) >> 40)) + +void simp_192_permute(unsigned char state[SIMP_192_STATE_SIZE], unsigned steps) +{ + uint64_t z = SIMP_RC; + uint64_t x0, x1, x2, x3, t0, t1; + unsigned round; + + /* Load the state into local variables */ + x0 = be_load_word48(state); + x1 = be_load_word48(state + 6); + x2 = be_load_word48(state + 12); + x3 = be_load_word48(state + 18); + + /* Perform all steps */ + for (; steps > 0; --steps) { + /* Perform all rounds for this step, two at a time */ + for (round = 0; round < (SIMP_192_ROUNDS / 2); ++round) { + t1 = x3 ^ (leftRotate1_48(x2) & leftRotate8_48(x2)) ^ + leftRotate2_48(x2) ^ x1; + t0 = x1 ^ rightRotate3_48(x0) ^ rightRotate4_48(x0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + t0 &= 0x0000FFFFFFFFFFFFULL; /* Truncate back to 48 bits */ + t1 &= 0x0000FFFFFFFFFFFFULL; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + x2 = x2 ^ (leftRotate1_48(t1) & leftRotate8_48(t1)) ^ + leftRotate2_48(t1) ^ x0; + x0 = x0 ^ rightRotate3_48(t0) ^ rightRotate4_48(t0) ^ + 0xFFFFFFFFFFFFFFFCULL ^ (z & 1); + x0 &= 0x0000FFFFFFFFFFFFULL; + x2 &= 0x0000FFFFFFFFFFFFULL; + x1 = t0; + x3 = t1; + z = (z >> 1) | (z << 61); /* z repeats every 62 rounds */ + } + + /* Swap the words of the state for all steps except the last */ + if (steps > 1) { + t0 = x0; + t1 = x1; + x0 = x2; + x1 = x3; + x2 = t0; + x3 = t1; + } + } + + /* Write the local variables back to the state */ + be_store_word48(state, x0); + be_store_word48(state + 6, x1); + be_store_word48(state + 12, x2); + be_store_word48(state + 18, x3); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.h b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.h new file mode 100644 index 0000000..3a95e80 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-simp.h @@ -0,0 +1,74 @@ +/* + * 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_SIMP_H +#define LW_INTERNAL_SIMP_H + +#include "internal-util.h" + +/** + * \file internal-simp.h + * \brief SimP permutation family. + * + * SimP-256 and SimP-192 are used by the Oribatida submission to + * round 2 of the NIST Lightweight Cryptography Competition. + * The permutations are built around reduced-round variants of the + * Simon-128-128 and Simon-96-96 block ciphers. + * + * References: https://www.isical.ac.in/~lightweight/oribatida/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief State size of the SimP-256 permutation. + */ +#define SIMP_256_STATE_SIZE 32 + +/** + * \brief State size of the SimP-192 permutation. + */ +#define SIMP_192_STATE_SIZE 24 + +/** + * \brief Permutes a state with SimP-256. + * + * \param state State to be permuted. + * \param steps Number of steps to perform (usually 2 or 4). + */ +void simp_256_permute(unsigned char state[SIMP_256_STATE_SIZE], unsigned steps); + +/** + * \brief Permutes a state with SimP-192. + * + * \param state State to be permuted. + * \param steps Number of steps to perform (usually 2 or 4). + */ +void simp_192_permute(unsigned char state[SIMP_192_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-util.h b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.c b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.c new file mode 100644 index 0000000..55a3914 --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.c @@ -0,0 +1,480 @@ +/* + * 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 "oribatida.h" +#include "internal-simp.h" +#include + +/** + * \brief Rate for processing data for the Oribatida-256-64 state. + */ +#define ORIBATIDA_256_RATE 16 + +/** + * \brief Size of the masking value for Oribatida-256-64. + */ +#define ORIBATIDA_256_MASK_SIZE 8 + +/** + * \brief Rate for processing data for the Oribatida-192-96 state. + */ +#define ORIBATIDA_192_RATE 12 + +/** + * \brief Size of the masking value for Oribatida-192-96. + */ +#define ORIBATIDA_192_MASK_SIZE 12 + +aead_cipher_t const oribatida_256_cipher = { + "Oribatida-256-64", + ORIBATIDA_256_KEY_SIZE, + ORIBATIDA_256_NONCE_SIZE, + ORIBATIDA_256_TAG_SIZE, + AEAD_FLAG_NONE, + oribatida_256_aead_encrypt, + oribatida_256_aead_decrypt +}; + +aead_cipher_t const oribatida_192_cipher = { + "Oribatida-192-96", + ORIBATIDA_192_KEY_SIZE, + ORIBATIDA_192_NONCE_SIZE, + ORIBATIDA_192_TAG_SIZE, + AEAD_FLAG_NONE, + oribatida_192_aead_encrypt, + oribatida_192_aead_decrypt +}; + +/* Definitions for domain separation values */ +#define ORIBATIDA_NUM_DOMAINS 3 +#define ORIBATIDA_DOMAIN_NONCE 0 +#define ORIBATIDA_DOMAIN_AD 1 +#define ORIBATIDA_DOMAIN_MSG 2 + +/** + * \brief Gets the domain separation values to use for different phases + * of the Oribatida encryption process. + * + * \param domains Returns the domain separation values to use. + * \param adlen Length of the associated data. + * \param mlen Length of the plaintext message. + * \param rate Rate of processing message blocks, 12 or 16. + */ +static void oribatida_get_domains + (unsigned char domains[ORIBATIDA_NUM_DOMAINS], + unsigned long long adlen, unsigned long long mlen, unsigned rate) +{ + /* Domain separation value for the nonce */ + if (adlen == 0 && mlen == 0) { + domains[ORIBATIDA_DOMAIN_NONCE] = 9; + } else { + domains[ORIBATIDA_DOMAIN_NONCE] = 5; + } + + /* Domain separation value for associated data processing */ + if (mlen == 0) { + if ((adlen % rate) == 0) + domains[ORIBATIDA_DOMAIN_AD] = 12; + else + domains[ORIBATIDA_DOMAIN_AD] = 14; + } else { + if ((adlen % rate) == 0) + domains[ORIBATIDA_DOMAIN_AD] = 4; + else + domains[ORIBATIDA_DOMAIN_AD] = 6; + } + + /* Domain separation value for message processing */ + if ((mlen % rate) == 0) { + domains[ORIBATIDA_DOMAIN_MSG] = 13; + } else { + domains[ORIBATIDA_DOMAIN_MSG] = 15; + } +} + +/** + * \brief Initializes the Oribatida-256-64 state. + * + * \param state Oribatida-256-64 permutation state. + * \param mask Oribatida-256-64 masking state. + * \param domains Precomputed domain separation values. + * \param k Points to the key. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void oribatida_256_init + (unsigned char state[SIMP_256_STATE_SIZE], + unsigned char mask[ORIBATIDA_256_MASK_SIZE], + const unsigned char domains[ORIBATIDA_NUM_DOMAINS], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state with the key and nonce */ + memcpy(state, npub, ORIBATIDA_256_NONCE_SIZE); + memcpy(state + ORIBATIDA_256_NONCE_SIZE, k, ORIBATIDA_256_KEY_SIZE); + + /* Use the current state as the mask for zero-length associated data */ + if (adlen == 0) { + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + } + + /* Add the domain separation value for the nonce */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_NONCE]; + + /* Run the permutation for the first time */ + simp_256_permute(state, 4); + + /* If there is no associated data, then we are done */ + if (adlen == 0) + return; + + /* Use the current state as the mask for non-zero length associated data */ + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + + /* Process all associated data blocks except the last */ + while (adlen > ORIBATIDA_256_RATE) { + lw_xor_block(state, ad, ORIBATIDA_256_RATE); + simp_256_permute(state, 2); + ad += ORIBATIDA_256_RATE; + adlen -= ORIBATIDA_256_RATE; + } + + /* Process the final associated data block */ + temp = (unsigned)adlen; + if (temp == ORIBATIDA_256_RATE) { + lw_xor_block(state, ad, ORIBATIDA_256_RATE); + } else { + lw_xor_block(state, ad, temp); + state[temp] ^= 0x80; /* padding */ + } + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_AD]; + simp_256_permute(state, 4); +} + +/** + * \brief Initializes the Oribatida-192-96 state. + * + * \param state Oribatida-192-96 permutation state. + * \param mask Oribatida-192-96 masking state. + * \param domains Precomputed domain separation values. + * \param k Points to the key. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void oribatida_192_init + (unsigned char state[SIMP_192_STATE_SIZE], + unsigned char mask[ORIBATIDA_192_MASK_SIZE], + const unsigned char domains[ORIBATIDA_NUM_DOMAINS], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state with the key and nonce */ + memcpy(state, npub, ORIBATIDA_192_NONCE_SIZE); + memcpy(state + ORIBATIDA_192_NONCE_SIZE, k, ORIBATIDA_256_KEY_SIZE); + + /* Use the current state as the mask for zero-length associated data */ + if (adlen == 0) { + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + } + + /* Add the domain separation value for the nonce */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_NONCE]; + + /* Run the permutation for the first time */ + simp_192_permute(state, 4); + + /* If there is no associated data, then we are done */ + if (adlen == 0) + return; + + /* Use the current state as the mask for non-zero length associated data */ + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + + /* Process all associated data blocks except the last */ + while (adlen > ORIBATIDA_192_RATE) { + lw_xor_block(state, ad, ORIBATIDA_192_RATE); + simp_192_permute(state, 2); + ad += ORIBATIDA_192_RATE; + adlen -= ORIBATIDA_192_RATE; + } + + /* Process the final associated data block */ + temp = (unsigned)adlen; + if (temp == ORIBATIDA_192_RATE) { + lw_xor_block(state, ad, ORIBATIDA_192_RATE); + } else { + lw_xor_block(state, ad, temp); + state[temp] ^= 0x80; /* padding */ + } + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_AD]; + simp_192_permute(state, 4); +} + +int oribatida_256_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) +{ + unsigned char state[SIMP_256_STATE_SIZE]; + unsigned char mask[ORIBATIDA_256_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ORIBATIDA_256_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + oribatida_get_domains(domains, adlen, mlen, ORIBATIDA_256_RATE); + oribatida_256_init(state, mask, domains, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen > ORIBATIDA_256_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_256_RATE); + lw_xor_block(c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + simp_256_permute(state, 4); + c += ORIBATIDA_256_RATE; + m += ORIBATIDA_256_RATE; + mlen -= ORIBATIDA_256_RATE; + } + if (mlen == ORIBATIDA_256_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_256_RATE); + lw_xor_block(c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } else if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state, m, temp); + if (temp > (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)) { + lw_xor_block + (c + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, mask, + temp - (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)); + } + state[temp] ^= 0x80; /* padding */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } + + /* Generate the authentication tag */ + memcpy(c + mlen, state, ORIBATIDA_256_TAG_SIZE); + return 0; +} + +int oribatida_256_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) +{ + unsigned char state[SIMP_256_STATE_SIZE]; + unsigned char mask[ORIBATIDA_256_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + unsigned char block[ORIBATIDA_256_RATE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ORIBATIDA_256_TAG_SIZE) + return -1; + *mlen = clen - ORIBATIDA_256_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + clen -= ORIBATIDA_256_TAG_SIZE; + oribatida_get_domains(domains, adlen, clen, ORIBATIDA_256_RATE); + oribatida_256_init(state, mask, domains, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + while (clen > ORIBATIDA_256_RATE) { + memcpy(block, c, ORIBATIDA_256_RATE); + lw_xor_block(block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_256_RATE); + memcpy(mask, state + SIMP_256_STATE_SIZE - ORIBATIDA_256_MASK_SIZE, + ORIBATIDA_256_MASK_SIZE); + simp_256_permute(state, 4); + c += ORIBATIDA_256_RATE; + m += ORIBATIDA_256_RATE; + clen -= ORIBATIDA_256_RATE; + } + if (clen == ORIBATIDA_256_RATE) { + memcpy(block, c, ORIBATIDA_256_RATE); + lw_xor_block(block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, + mask, ORIBATIDA_256_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_256_RATE); + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } else if (clen > 0) { + unsigned temp = (unsigned)clen; + memcpy(block, c, temp); + if (temp > (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)) { + lw_xor_block + (block + ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE, mask, + temp - (ORIBATIDA_256_RATE - ORIBATIDA_256_MASK_SIZE)); + } + lw_xor_block_swap(m, state, block, temp); + state[temp] ^= 0x80; /* padding */ + state[SIMP_256_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_256_permute(state, 4); + } + c += clen; + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state, c, ORIBATIDA_256_TAG_SIZE); +} + +int oribatida_192_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) +{ + unsigned char state[SIMP_192_STATE_SIZE]; + unsigned char mask[ORIBATIDA_192_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ORIBATIDA_192_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + oribatida_get_domains(domains, adlen, mlen, ORIBATIDA_192_RATE); + oribatida_192_init(state, mask, domains, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen > ORIBATIDA_192_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_192_RATE); + lw_xor_block(c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + simp_192_permute(state, 4); + c += ORIBATIDA_192_RATE; + m += ORIBATIDA_192_RATE; + mlen -= ORIBATIDA_192_RATE; + } + if (mlen == ORIBATIDA_192_RATE) { + lw_xor_block_2_dest(c, state, m, ORIBATIDA_192_RATE); + lw_xor_block(c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } else if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state, m, temp); + if (temp > (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)) { + lw_xor_block + (c + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, mask, + temp - (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)); + } + state[temp] ^= 0x80; /* padding */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } + + /* Generate the authentication tag */ + memcpy(c + mlen, state, ORIBATIDA_192_TAG_SIZE); + return 0; +} + +int oribatida_192_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) +{ + unsigned char state[SIMP_192_STATE_SIZE]; + unsigned char mask[ORIBATIDA_192_MASK_SIZE]; + unsigned char domains[ORIBATIDA_NUM_DOMAINS]; + unsigned char block[ORIBATIDA_192_RATE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ORIBATIDA_192_TAG_SIZE) + return -1; + *mlen = clen - ORIBATIDA_192_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + clen -= ORIBATIDA_192_TAG_SIZE; + oribatida_get_domains(domains, adlen, clen, ORIBATIDA_192_RATE); + oribatida_192_init(state, mask, domains, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + while (clen > ORIBATIDA_192_RATE) { + memcpy(block, c, ORIBATIDA_192_RATE); + lw_xor_block(block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_192_RATE); + memcpy(mask, state + SIMP_192_STATE_SIZE - ORIBATIDA_192_MASK_SIZE, + ORIBATIDA_192_MASK_SIZE); + simp_192_permute(state, 4); + c += ORIBATIDA_192_RATE; + m += ORIBATIDA_192_RATE; + clen -= ORIBATIDA_192_RATE; + } + if (clen == ORIBATIDA_192_RATE) { + memcpy(block, c, ORIBATIDA_192_RATE); + lw_xor_block(block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, + mask, ORIBATIDA_192_MASK_SIZE); + lw_xor_block_swap(m, state, block, ORIBATIDA_192_RATE); + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } else if (clen > 0) { + unsigned temp = (unsigned)clen; + memcpy(block, c, temp); + if (temp > (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)) { + lw_xor_block + (block + ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE, mask, + temp - (ORIBATIDA_192_RATE - ORIBATIDA_192_MASK_SIZE)); + } + lw_xor_block_swap(m, state, block, temp); + state[temp] ^= 0x80; /* padding */ + state[SIMP_192_STATE_SIZE - 1] ^= domains[ORIBATIDA_DOMAIN_MSG]; + simp_192_permute(state, 4); + } + c += clen; + + /* Check the authentication tag */ + return aead_check_tag(mtemp, *mlen, state, c, ORIBATIDA_192_TAG_SIZE); +} diff --git a/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.h b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.h new file mode 100644 index 0000000..dbc374b --- /dev/null +++ b/oribatida/Implementations/crypto_aead/oribatida256v12/rhys/oribatida.h @@ -0,0 +1,212 @@ +/* + * 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_ORIBATIDA_H +#define LWCRYPTO_ORIBATIDA_H + +#include "aead-common.h" + +/** + * \file oribatida.h + * \brief Oribatida authenticated encryption algorithm. + * + * Oribatida is a family of authenticated encryption algorithms based on the + * SimP-256 and SimP-192 permutations which are built around reduced-round + * variants of the Simon-128-128 and Simon-96-96 block ciphers. + * There are two algorithms in the family: + * + * \li Oribatida-256-64 with a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * built around the SimP-256 permutation. This is the primary member of + * the family. + * \li Oribatida-192-96 with a 128-bit key, a 64-bit nonce, and a 96-bit tag, + * built around the SimP-192 permutation. + * + * References: https://www.isical.ac.in/~lightweight/oribatida/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Oribatida-256-64. + */ +#define ORIBATIDA_256_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Oribatida-256-64. + */ +#define ORIBATIDA_256_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Oribatida-256-64. + */ +#define ORIBATIDA_256_NONCE_SIZE 16 + +/** + * \brief Size of the key for Oribatida-192-96. + */ +#define ORIBATIDA_192_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Oribatida-192-96. + */ +#define ORIBATIDA_192_TAG_SIZE 12 + +/** + * \brief Size of the nonce for Oribatida-192-96. + */ +#define ORIBATIDA_192_NONCE_SIZE 8 + +/** + * \brief Meta-information block for the Oribatida-256-64 cipher. + */ +extern aead_cipher_t const oribatida_256_cipher; + +/** + * \brief Meta-information block for the Oribatida-192-96 cipher. + */ +extern aead_cipher_t const oribatida_192_cipher; + +/** + * \brief Encrypts and authenticates a packet with Oribatida-256-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa oribatida_256_aead_decrypt() + */ +int oribatida_256_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); + +/** + * \brief Decrypts and authenticates a packet with Oribatida-256-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa oribatida_256_aead_encrypt() + */ +int oribatida_256_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); + +/** + * \brief Encrypts and authenticates a packet with Oribatida-192-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa oribatida_192_aead_decrypt() + */ +int oribatida_192_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); + +/** + * \brief Decrypts and authenticates a packet with Oribatida-192-96. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa oribatida_192_aead_encrypt() + */ +int oribatida_192_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/api.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/encrypt.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/encrypt.c new file mode 100644 index 0000000..a36c2ea --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "photon-beetle.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 photon_beetle_128_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 photon_beetle_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.c new file mode 100644 index 0000000..b8743fe --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.c @@ -0,0 +1,479 @@ +/* + * 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 "internal-photon256.h" +#include "internal-util.h" + +/** + * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. + */ +#define PHOTON256_ROUNDS 12 + +/* Round constants for PHOTON-256 */ +static uint32_t const photon256_rc[PHOTON256_ROUNDS] = { + 0x96d2f0e1, 0xb4f0d2c3, 0xf0b49687, 0x692d0f1e, + 0x5a1e3c2d, 0x3c785a4b, 0xe1a58796, 0x4b0f2d3c, + 0x1e5a7869, 0xa5e1c3d2, 0xd296b4a5, 0x2d694b5a +}; + +/** + * \brief Evaluates the PHOTON-256 S-box in bit-sliced form. + * + * \param x0 Slice with bit 0 of all nibbles. + * \param x1 Slice with bit 1 of all nibbles. + * \param x2 Slice with bit 2 of all nibbles. + * \param x3 Slice with bit 3 of all nibbles. + * + * This bit-sliced S-box implementation is based on the AVR version + * "add_avr8_bitslice_asm" from the PHOTON-Beetle reference code. + */ +#define photon256_sbox(x0, x1, x2, x3) \ + do { \ + x1 ^= x2; \ + x3 ^= (x2 & x1); \ + t1 = x3; \ + x3 = (x3 & x1) ^ x2; \ + t2 = x3; \ + x3 ^= x0; \ + x3 = ~(x3); \ + x2 = x3; \ + t2 |= x0; \ + x0 ^= t1; \ + x1 ^= x0; \ + x2 |= x1; \ + x2 ^= t1; \ + x1 ^= t2; \ + x3 ^= x1; \ + } while (0) + +/** + * \brief Performs a field multiplication on the 8 nibbles in a row. + * + * \param a Field constant to multiply by. + * \param x Bit-sliced form of the row, with bits 0..3 of each nibble + * in bytes 0..3 of the word. + * + * \return a * x packed into the bytes of a word. + */ +static uint32_t photon256_field_multiply(uint8_t a, uint32_t x) +{ + /* For each 4-bit nibble we need to do this: + * + * result = 0; + * for (bit = 0; bit < 4; ++ bit) { + * if ((a & (1 << bit)) != 0) + * result ^= x; + * if ((x & 0x08) != 0) { + * x = (x << 1) ^ 3; + * } else { + * x = (x << 1); + * } + * } + * + * We don't need to worry about constant time for "a" because it is a + * known constant that isn't data-dependent. But we do need to worry + * about constant time for "x" as it is data. + */ + uint32_t result = 0; + uint32_t t; + #define PARALLEL_CONDITIONAL_ADD(bit) \ + do { \ + if ((a) & (1 << (bit))) \ + result ^= x; \ + } while (0) + #define PARALELL_ROTATE() \ + do { \ + t = x >> 24; \ + x = (x << 8) ^ t ^ (t << 8); \ + } while (0) + PARALLEL_CONDITIONAL_ADD(0); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(1); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(2); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(3); + return result; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts a PHOTON-256 state into bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_to_sliced + (uint32_t out[PHOTON256_STATE_SIZE / 4], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* We first scatter bits 0..3 of the nibbles to bytes 0..3 of the words. + * Then we rearrange the bytes to group all bits N into word N. + * + * Permutation generated with "http://programming.sirrida.de/calcperm.php". + * + * P = [0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 + * 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31] + */ + uint32_t t0, t1, t2, t3; + #define TO_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + #define FROM_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + t0 = le_load_word32(in); + t1 = le_load_word32(in + 4); + t2 = le_load_word32(in + 8); + t3 = le_load_word32(in + 12); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[0] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[1] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[2] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[3] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); + t0 = le_load_word32(in + 16); + t1 = le_load_word32(in + 20); + t2 = le_load_word32(in + 24); + t3 = le_load_word32(in + 28); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[4] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[5] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[6] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[7] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); +} + +/** + * \brief Converts a PHOTON-256 state from bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_from_sliced + (unsigned char out[PHOTON256_STATE_SIZE], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* Do the reverse of photon256_to_sliced() */ + uint32_t x0, x1, x2, x3; + x0 = ((uint32_t)(in[0])) | + (((uint32_t)(in[4])) << 8) | + (((uint32_t)(in[8])) << 16) | + (((uint32_t)(in[12])) << 24); + x1 = ((uint32_t)(in[1])) | + (((uint32_t)(in[5])) << 8) | + (((uint32_t)(in[9])) << 16) | + (((uint32_t)(in[13])) << 24); + x2 = ((uint32_t)(in[2])) | + (((uint32_t)(in[6])) << 8) | + (((uint32_t)(in[10])) << 16) | + (((uint32_t)(in[14])) << 24); + x3 = ((uint32_t)(in[3])) | + (((uint32_t)(in[7])) << 8) | + (((uint32_t)(in[11])) << 16) | + (((uint32_t)(in[15])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out, x0); + le_store_word32(out + 4, x1); + le_store_word32(out + 8, x2); + le_store_word32(out + 12, x3); + x0 = ((uint32_t)(in[16])) | + (((uint32_t)(in[20])) << 8) | + (((uint32_t)(in[24])) << 16) | + (((uint32_t)(in[28])) << 24); + x1 = ((uint32_t)(in[17])) | + (((uint32_t)(in[21])) << 8) | + (((uint32_t)(in[25])) << 16) | + (((uint32_t)(in[29])) << 24); + x2 = ((uint32_t)(in[18])) | + (((uint32_t)(in[22])) << 8) | + (((uint32_t)(in[26])) << 16) | + (((uint32_t)(in[30])) << 24); + x3 = ((uint32_t)(in[19])) | + (((uint32_t)(in[23])) << 8) | + (((uint32_t)(in[27])) << 16) | + (((uint32_t)(in[31])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out + 16, x0); + le_store_word32(out + 20, x1); + le_store_word32(out + 24, x2); + le_store_word32(out + 28, x3); +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +/* Index the bit-sliced state bytes in little-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[(row)] = (uint8_t)(value); \ + S.bytes[(row) + 4] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 8] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 12] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[(row) + 12] = (uint8_t)(value); \ + S.bytes[(row) + 16] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 20] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 24] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#else +/* Index the bit-sliced state bytes in big-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[3 - (row)] = (uint8_t)(value); \ + S.bytes[7 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[11 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[15 - (row)] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[20 - (row)] = (uint8_t)(value); \ + S.bytes[24 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[28 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[32 - (row)] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#endif + +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) +{ + union { + uint32_t words[PHOTON256_STATE_SIZE / 4]; + uint8_t bytes[PHOTON256_STATE_SIZE]; + } S; + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + uint8_t round; + + /* Convert the state into bit-sliced form */ + photon256_to_sliced(S.words, state); + + /* Perform all 12 permutation rounds */ + for (round = 0; round < PHOTON256_ROUNDS; ++round) { + /* Add the constants for this round */ + t0 = photon256_rc[round]; + S.words[0] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[1] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[2] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[3] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[4] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[5] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[6] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[7] ^= t0 & 0x01010101U; + + /* Apply the sbox to all nibbles in the state */ + photon256_sbox(S.words[0], S.words[1], S.words[2], S.words[3]); + photon256_sbox(S.words[4], S.words[5], S.words[6], S.words[7]); + + /* Rotate all rows left by the row number. + * + * We do this by applying permutations to the top and bottom words + * to rearrange the bits into the rotated form. Permutations + * generated with "http://programming.sirrida.de/calcperm.php". + * + * P_top = [0 1 2 3 4 5 6 7 15 8 9 10 11 12 13 14 22 23 + * 16 17 18 19 20 21 29 30 31 24 25 26 27 28] + * P_bot = [4 5 6 7 0 1 2 3 11 12 13 14 15 8 9 10 18 19 + * 20 21 22 23 16 17 25 26 27 28 29 30 31 24 + */ + #define TOP_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x07030100, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + #define BOTTOM_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x080c0e0f, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + TOP_ROTATE_PERM(S.words[0]); + TOP_ROTATE_PERM(S.words[1]); + TOP_ROTATE_PERM(S.words[2]); + TOP_ROTATE_PERM(S.words[3]); + BOTTOM_ROTATE_PERM(S.words[4]); + BOTTOM_ROTATE_PERM(S.words[5]); + BOTTOM_ROTATE_PERM(S.words[6]); + BOTTOM_ROTATE_PERM(S.words[7]); + + /* Mix the columns */ + #define MUL(a, x) (photon256_field_multiply((a), (x))) + t0 = READ_ROW0(); + t1 = READ_ROW1(); + t2 = READ_ROW2(); + t3 = READ_ROW3(); + t4 = READ_ROW4(); + t5 = READ_ROW5(); + t6 = READ_ROW6(); + t7 = READ_ROW7(); + t8 = MUL(0x02, t0) ^ MUL(0x04, t1) ^ MUL(0x02, t2) ^ MUL(0x0b, t3) ^ + MUL(0x02, t4) ^ MUL(0x08, t5) ^ MUL(0x05, t6) ^ MUL(0x06, t7); + WRITE_ROW(0, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x09, t1) ^ MUL(0x08, t2) ^ MUL(0x0d, t3) ^ + MUL(0x07, t4) ^ MUL(0x07, t5) ^ MUL(0x05, t6) ^ MUL(0x02, t7); + WRITE_ROW(1, t8); + t8 = MUL(0x04, t0) ^ MUL(0x04, t1) ^ MUL(0x0d, t2) ^ MUL(0x0d, t3) ^ + MUL(0x09, t4) ^ MUL(0x04, t5) ^ MUL(0x0d, t6) ^ MUL(0x09, t7); + WRITE_ROW(2, t8); + t8 = MUL(0x01, t0) ^ MUL(0x06, t1) ^ MUL(0x05, t2) ^ MUL(0x01, t3) ^ + MUL(0x0c, t4) ^ MUL(0x0d, t5) ^ MUL(0x0f, t6) ^ MUL(0x0e, t7); + WRITE_ROW(3, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x0c, t1) ^ MUL(0x09, t2) ^ MUL(0x0d, t3) ^ + MUL(0x0e, t4) ^ MUL(0x05, t5) ^ MUL(0x0e, t6) ^ MUL(0x0d, t7); + WRITE_ROW(4, t8); + t8 = MUL(0x09, t0) ^ MUL(0x0e, t1) ^ MUL(0x05, t2) ^ MUL(0x0f, t3) ^ + MUL(0x04, t4) ^ MUL(0x0c, t5) ^ MUL(0x09, t6) ^ MUL(0x06, t7); + WRITE_ROW(5, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x02, t1) ^ MUL(0x02, t2) ^ MUL(0x0a, t3) ^ + MUL(0x03, t4) ^ MUL(0x01, t5) ^ MUL(0x01, t6) ^ MUL(0x0e, t7); + WRITE_ROW(6, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x01, t1) ^ MUL(0x0d, t2) ^ MUL(0x0a, t3) ^ + MUL(0x05, t4) ^ MUL(0x0a, t5) ^ MUL(0x02, t6) ^ MUL(0x03, t7); + WRITE_ROW(7, t8); + } + + /* Convert back from bit-sliced form to regular form */ + photon256_from_sliced(state, S.bytes); +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.h new file mode 100644 index 0000000..ce8729a --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-photon256.h @@ -0,0 +1,54 @@ +/* + * 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_PHOTON256_H +#define LW_INTERNAL_PHOTON256_H + +/** + * \file internal-photon256.h + * \brief Internal implementation of the PHOTON-256 permutation. + * + * Warning: The current implementation of PHOTON-256 is constant-time + * but not constant-cache. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the PHOTON-256 permutation state in bytes. + */ +#define PHOTON256_STATE_SIZE 32 + +/** + * \brief Permutes the PHOTON-256 state. + * + * \param state The state to be permuted. + */ +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-util.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.c new file mode 100644 index 0000000..f44bdad --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.c @@ -0,0 +1,451 @@ +/* + * 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 "photon-beetle.h" +#include "internal-photon256.h" +#include "internal-util.h" +#include + +aead_cipher_t const photon_beetle_128_cipher = { + "PHOTON-Beetle-AEAD-ENC-128", + PHOTON_BEETLE_KEY_SIZE, + PHOTON_BEETLE_NONCE_SIZE, + PHOTON_BEETLE_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + photon_beetle_128_aead_encrypt, + photon_beetle_128_aead_decrypt +}; + +aead_cipher_t const photon_beetle_32_cipher = { + "PHOTON-Beetle-AEAD-ENC-32", + PHOTON_BEETLE_KEY_SIZE, + PHOTON_BEETLE_NONCE_SIZE, + PHOTON_BEETLE_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + photon_beetle_32_aead_encrypt, + photon_beetle_32_aead_decrypt +}; + +aead_hash_algorithm_t const photon_beetle_hash_algorithm = { + "PHOTON-Beetle-HASH", + sizeof(int), + PHOTON_BEETLE_HASH_SIZE, + AEAD_FLAG_NONE, + photon_beetle_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 Rate of operation for PHOTON-Beetle-AEAD-ENC-128. + */ +#define PHOTON_BEETLE_128_RATE 16 + +/** + * \brief Rate of operation for PHOTON-Beetle-AEAD-ENC-32. + */ +#define PHOTON_BEETLE_32_RATE 4 + +/* Shifts a domain constant from the spec to the correct bit position */ +#define DOMAIN(c) ((c) << 5) + +/** + * \brief Processes the associated data for PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be non-zero. + * \param rate Rate of absorption for the data. + * \param mempty Non-zero if the message is empty. + */ +static void photon_beetle_process_ad + (unsigned char state[PHOTON256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen, + unsigned rate, int mempty) +{ + unsigned temp; + + /* Absorb as many full rate blocks as possible */ + while (adlen > rate) { + photon256_permute(state); + lw_xor_block(state, ad, rate); + ad += rate; + adlen -= rate; + } + + /* Pad and absorb the last block */ + temp = (unsigned)adlen; + photon256_permute(state); + lw_xor_block(state, ad, temp); + if (temp < rate) + state[temp] ^= 0x01; /* padding */ + + /* Add the domain constant to finalize associated data processing */ + if (mempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(3); + else if (mempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(4); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +/** + * \brief Rotates part of the PHOTON-256 state right by one bit. + * + * \param out Output state buffer. + * \param in Input state buffer, must not overlap with \a out. + * \param len Length of the state buffer. + */ +static void photon_beetle_rotate1 + (unsigned char *out, const unsigned char *in, unsigned len) +{ + unsigned posn; + for (posn = 0; posn < (len - 1); ++posn) + out[posn] = (in[posn] >> 1) | (in[posn + 1] << 7); + out[len - 1] = (in[len - 1] >> 1) | (in[0] << 7); +} + +/** + * \brief Encrypts a plaintext block with PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Length of the message, must be non-zero. + * \param rate Rate of absorption for the data. + * \param adempty Non-zero if the associated data is empty. + */ +static void photon_beetle_encrypt + (unsigned char state[PHOTON256_STATE_SIZE], + unsigned char *c, const unsigned char *m, unsigned long long mlen, + unsigned rate, int adempty) +{ + unsigned char shuffle[PHOTON_BEETLE_128_RATE]; /* Block of max rate size */ + unsigned temp; + + /* Process all plaintext blocks except the last */ + while (mlen > rate) { + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + lw_xor_block(state, m, rate); + lw_xor_block_2_src(c, m, shuffle, rate); + c += rate; + m += rate; + mlen -= rate; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + if (temp == rate) { + lw_xor_block(state, m, rate); + lw_xor_block_2_src(c, m, shuffle, rate); + } else { + lw_xor_block(state, m, temp); + state[temp] ^= 0x01; /* padding */ + lw_xor_block_2_src(c, m, shuffle, temp); + } + + /* Add the domain constant to finalize message processing */ + if (adempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(5); + else if (adempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(6); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +/** + * \brief Decrypts a ciphertext block with PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param mlen Length of the message, must be non-zero. + * \param rate Rate of absorption for the data. + * \param adempty Non-zero if the associated data is empty. + */ +static void photon_beetle_decrypt + (unsigned char state[PHOTON256_STATE_SIZE], + unsigned char *m, const unsigned char *c, unsigned long long mlen, + unsigned rate, int adempty) +{ + unsigned char shuffle[PHOTON_BEETLE_128_RATE]; /* Block of max rate size */ + unsigned temp; + + /* Process all plaintext blocks except the last */ + while (mlen > rate) { + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + lw_xor_block_2_src(m, c, shuffle, rate); + lw_xor_block(state, m, rate); + c += rate; + m += rate; + mlen -= rate; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + if (temp == rate) { + lw_xor_block_2_src(m, c, shuffle, rate); + lw_xor_block(state, m, rate); + } else { + lw_xor_block_2_src(m, c, shuffle, temp); + lw_xor_block(state, m, temp); + state[temp] ^= 0x01; /* padding */ + } + + /* Add the domain constant to finalize message processing */ + if (adempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(5); + else if (adempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(6); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +int photon_beetle_128_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_128_RATE, mlen == 0); + } else if (mlen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + photon_beetle_encrypt + (state, c, m, mlen, PHOTON_BEETLE_128_RATE, adlen == 0); + } + + /* Generate the authentication tag */ + photon256_permute(state); + memcpy(c + mlen, state, PHOTON_BEETLE_TAG_SIZE); + return 0; +} + +int photon_beetle_128_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < PHOTON_BEETLE_TAG_SIZE) + return -1; + *mlen = clen - PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + clen -= PHOTON_BEETLE_TAG_SIZE; + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_128_RATE, clen == 0); + } else if (clen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + photon_beetle_decrypt + (state, m, c, clen, PHOTON_BEETLE_128_RATE, adlen == 0); + } + + /* Check the authentication tag */ + photon256_permute(state); + return aead_check_tag(m, clen, state, c + clen, PHOTON_BEETLE_TAG_SIZE); +} + +int photon_beetle_32_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_32_RATE, mlen == 0); + } else if (mlen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + photon_beetle_encrypt + (state, c, m, mlen, PHOTON_BEETLE_32_RATE, adlen == 0); + } + + /* Generate the authentication tag */ + photon256_permute(state); + memcpy(c + mlen, state, PHOTON_BEETLE_TAG_SIZE); + return 0; +} + +int photon_beetle_32_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < PHOTON_BEETLE_TAG_SIZE) + return -1; + *mlen = clen - PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + clen -= PHOTON_BEETLE_TAG_SIZE; + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_32_RATE, clen == 0); + } else if (clen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + photon_beetle_decrypt + (state, m, c, clen, PHOTON_BEETLE_32_RATE, adlen == 0); + } + + /* Check the authentication tag */ + photon256_permute(state); + return aead_check_tag(m, clen, state, c + clen, PHOTON_BEETLE_TAG_SIZE); +} + +int photon_beetle_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + unsigned temp; + + /* Absorb the input data */ + if (inlen == 0) { + /* No input data at all */ + memset(state, 0, sizeof(state) - 1); + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(1); + } else if (inlen <= PHOTON_BEETLE_128_RATE) { + /* Only one block of input data, which may require padding */ + temp = (unsigned)inlen; + memcpy(state, in, temp); + memset(state + temp, 0, sizeof(state) - temp - 1); + if (temp < PHOTON_BEETLE_128_RATE) { + state[temp] = 0x01; + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(1); + } else { + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(2); + } + } else { + /* Initialize the state with the first block, then absorb the rest */ + memcpy(state, in, PHOTON_BEETLE_128_RATE); + memset(state + PHOTON_BEETLE_128_RATE, 0, + sizeof(state) - PHOTON_BEETLE_128_RATE); + in += PHOTON_BEETLE_128_RATE; + inlen -= PHOTON_BEETLE_128_RATE; + while (inlen > PHOTON_BEETLE_32_RATE) { + photon256_permute(state); + lw_xor_block(state, in, PHOTON_BEETLE_32_RATE); + in += PHOTON_BEETLE_32_RATE; + inlen -= PHOTON_BEETLE_32_RATE; + } + photon256_permute(state); + temp = (unsigned)inlen; + if (temp == PHOTON_BEETLE_32_RATE) { + lw_xor_block(state, in, PHOTON_BEETLE_32_RATE); + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } else { + lw_xor_block(state, in, temp); + state[temp] ^= 0x01; + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); + } + } + + /* Generate the output hash */ + photon256_permute(state); + memcpy(out, state, 16); + photon256_permute(state); + memcpy(out + 16, state, 16); + return 0; +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.h new file mode 100644 index 0000000..2d94a7e --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate128v1/rhys/photon-beetle.h @@ -0,0 +1,224 @@ +/* + * 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_PHOTON_BEETLE_H +#define LWCRYPTO_PHOTON_BEETLE_H + +#include "aead-common.h" + +/** + * \file photon-beetle.h + * \brief PHOTON-Beetle authenticated encryption algorithm. + * + * PHOTON-Beetle is a family of authenticated encryption algorithms based + * on the PHOTON-256 permutation and using the Beetle sponge mode. + * There are three algorithms in the family: + * + * \li PHOTON-Beetle-AEAD-ENC-128 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag. Data is handled in 16 byte blocks. This is the primary + * member of the family for encryption. + * \li PHOTON-Beetle-AEAD-ENC-32 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag. Data is handled in 4 byte blocks. + * \li PHOTON-Beetle-Hash with a 256-bit hash output. The initial data is + * handled as a 16 byte block, and then the remaining bytes are processed + * in 4 byte blocks. + * + * References: https://www.isical.ac.in/~lightweight/beetle/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for PHOTON-Beetle-HASH. + */ +#define PHOTON_BEETLE_HASH_SIZE 32 + +/** + * \brief Meta-information block for the PHOTON-Beetle-AEAD-ENC-128 cipher. + */ +extern aead_cipher_t const photon_beetle_128_cipher; + +/** + * \brief Meta-information block for the PHOTON-Beetle-AEAD-ENC-32 cipher. + */ +extern aead_cipher_t const photon_beetle_32_cipher; + +/** + * \brief Meta-information block for the PHOTON-Beetle-HASH algorithm. + */ +extern aead_hash_algorithm_t const photon_beetle_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa photon_beetle_128_aead_decrypt() + */ +int photon_beetle_128_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); + +/** + * \brief Decrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa photon_beetle_128_aead_encrypt() + */ +int photon_beetle_128_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); + +/** + * \brief Encrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-32. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa photon_beetle_32_aead_decrypt() + */ +int photon_beetle_32_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); + +/** + * \brief Decrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-32. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa photon_beetle_32_aead_encrypt() + */ +int photon_beetle_32_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); + +/** + * \brief Hashes a block of input data with PHOTON-Beetle-HASH to + * generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * PHOTON_BEETLE_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 photon_beetle_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/api.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/encrypt.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/encrypt.c new file mode 100644 index 0000000..17af9cd --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "photon-beetle.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 photon_beetle_32_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 photon_beetle_32_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.c new file mode 100644 index 0000000..b8743fe --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.c @@ -0,0 +1,479 @@ +/* + * 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 "internal-photon256.h" +#include "internal-util.h" + +/** + * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. + */ +#define PHOTON256_ROUNDS 12 + +/* Round constants for PHOTON-256 */ +static uint32_t const photon256_rc[PHOTON256_ROUNDS] = { + 0x96d2f0e1, 0xb4f0d2c3, 0xf0b49687, 0x692d0f1e, + 0x5a1e3c2d, 0x3c785a4b, 0xe1a58796, 0x4b0f2d3c, + 0x1e5a7869, 0xa5e1c3d2, 0xd296b4a5, 0x2d694b5a +}; + +/** + * \brief Evaluates the PHOTON-256 S-box in bit-sliced form. + * + * \param x0 Slice with bit 0 of all nibbles. + * \param x1 Slice with bit 1 of all nibbles. + * \param x2 Slice with bit 2 of all nibbles. + * \param x3 Slice with bit 3 of all nibbles. + * + * This bit-sliced S-box implementation is based on the AVR version + * "add_avr8_bitslice_asm" from the PHOTON-Beetle reference code. + */ +#define photon256_sbox(x0, x1, x2, x3) \ + do { \ + x1 ^= x2; \ + x3 ^= (x2 & x1); \ + t1 = x3; \ + x3 = (x3 & x1) ^ x2; \ + t2 = x3; \ + x3 ^= x0; \ + x3 = ~(x3); \ + x2 = x3; \ + t2 |= x0; \ + x0 ^= t1; \ + x1 ^= x0; \ + x2 |= x1; \ + x2 ^= t1; \ + x1 ^= t2; \ + x3 ^= x1; \ + } while (0) + +/** + * \brief Performs a field multiplication on the 8 nibbles in a row. + * + * \param a Field constant to multiply by. + * \param x Bit-sliced form of the row, with bits 0..3 of each nibble + * in bytes 0..3 of the word. + * + * \return a * x packed into the bytes of a word. + */ +static uint32_t photon256_field_multiply(uint8_t a, uint32_t x) +{ + /* For each 4-bit nibble we need to do this: + * + * result = 0; + * for (bit = 0; bit < 4; ++ bit) { + * if ((a & (1 << bit)) != 0) + * result ^= x; + * if ((x & 0x08) != 0) { + * x = (x << 1) ^ 3; + * } else { + * x = (x << 1); + * } + * } + * + * We don't need to worry about constant time for "a" because it is a + * known constant that isn't data-dependent. But we do need to worry + * about constant time for "x" as it is data. + */ + uint32_t result = 0; + uint32_t t; + #define PARALLEL_CONDITIONAL_ADD(bit) \ + do { \ + if ((a) & (1 << (bit))) \ + result ^= x; \ + } while (0) + #define PARALELL_ROTATE() \ + do { \ + t = x >> 24; \ + x = (x << 8) ^ t ^ (t << 8); \ + } while (0) + PARALLEL_CONDITIONAL_ADD(0); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(1); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(2); + PARALELL_ROTATE(); + PARALLEL_CONDITIONAL_ADD(3); + return result; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts a PHOTON-256 state into bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_to_sliced + (uint32_t out[PHOTON256_STATE_SIZE / 4], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* We first scatter bits 0..3 of the nibbles to bytes 0..3 of the words. + * Then we rearrange the bytes to group all bits N into word N. + * + * Permutation generated with "http://programming.sirrida.de/calcperm.php". + * + * P = [0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 + * 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31] + */ + uint32_t t0, t1, t2, t3; + #define TO_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + #define FROM_BITSLICED_PERM(x) \ + do { \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + } while (0) + t0 = le_load_word32(in); + t1 = le_load_word32(in + 4); + t2 = le_load_word32(in + 8); + t3 = le_load_word32(in + 12); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[0] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[1] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[2] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[3] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); + t0 = le_load_word32(in + 16); + t1 = le_load_word32(in + 20); + t2 = le_load_word32(in + 24); + t3 = le_load_word32(in + 28); + TO_BITSLICED_PERM(t0); + TO_BITSLICED_PERM(t1); + TO_BITSLICED_PERM(t2); + TO_BITSLICED_PERM(t3); + out[4] = (t0 & 0x000000FFU) | ((t1 << 8) & 0x0000FF00U) | + ((t2 << 16) & 0x00FF0000U) | ((t3 << 24) & 0xFF000000U); + out[5] = ((t0 >> 8) & 0x000000FFU) | (t1 & 0x0000FF00U) | + ((t2 << 8) & 0x00FF0000U) | ((t3 << 16) & 0xFF000000U); + out[6] = ((t0 >> 16) & 0x000000FFU) | ((t1 >> 8) & 0x0000FF00U) | + (t2 & 0x00FF0000U) | ((t3 << 8) & 0xFF000000U); + out[7] = ((t0 >> 24) & 0x000000FFU) | ((t1 >> 16) & 0x0000FF00U) | + ((t2 >> 8) & 0x00FF0000U) | (t3 & 0xFF000000U); +} + +/** + * \brief Converts a PHOTON-256 state from bit-sliced form. + * + * \param out Points to the converted output. + * \param in Points to the PHOTON-256 state to convert. + */ +static void photon256_from_sliced + (unsigned char out[PHOTON256_STATE_SIZE], + const unsigned char in[PHOTON256_STATE_SIZE]) +{ + /* Do the reverse of photon256_to_sliced() */ + uint32_t x0, x1, x2, x3; + x0 = ((uint32_t)(in[0])) | + (((uint32_t)(in[4])) << 8) | + (((uint32_t)(in[8])) << 16) | + (((uint32_t)(in[12])) << 24); + x1 = ((uint32_t)(in[1])) | + (((uint32_t)(in[5])) << 8) | + (((uint32_t)(in[9])) << 16) | + (((uint32_t)(in[13])) << 24); + x2 = ((uint32_t)(in[2])) | + (((uint32_t)(in[6])) << 8) | + (((uint32_t)(in[10])) << 16) | + (((uint32_t)(in[14])) << 24); + x3 = ((uint32_t)(in[3])) | + (((uint32_t)(in[7])) << 8) | + (((uint32_t)(in[11])) << 16) | + (((uint32_t)(in[15])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out, x0); + le_store_word32(out + 4, x1); + le_store_word32(out + 8, x2); + le_store_word32(out + 12, x3); + x0 = ((uint32_t)(in[16])) | + (((uint32_t)(in[20])) << 8) | + (((uint32_t)(in[24])) << 16) | + (((uint32_t)(in[28])) << 24); + x1 = ((uint32_t)(in[17])) | + (((uint32_t)(in[21])) << 8) | + (((uint32_t)(in[25])) << 16) | + (((uint32_t)(in[29])) << 24); + x2 = ((uint32_t)(in[18])) | + (((uint32_t)(in[22])) << 8) | + (((uint32_t)(in[26])) << 16) | + (((uint32_t)(in[30])) << 24); + x3 = ((uint32_t)(in[19])) | + (((uint32_t)(in[23])) << 8) | + (((uint32_t)(in[27])) << 16) | + (((uint32_t)(in[31])) << 24); + FROM_BITSLICED_PERM(x0); + FROM_BITSLICED_PERM(x1); + FROM_BITSLICED_PERM(x2); + FROM_BITSLICED_PERM(x3); + le_store_word32(out + 16, x0); + le_store_word32(out + 20, x1); + le_store_word32(out + 24, x2); + le_store_word32(out + 28, x3); +} + +#if defined(LW_UTIL_LITTLE_ENDIAN) +/* Index the bit-sliced state bytes in little-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[(row)] = (uint8_t)(value); \ + S.bytes[(row) + 4] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 8] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 12] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[(row) + 12] = (uint8_t)(value); \ + S.bytes[(row) + 16] = (uint8_t)((value) >> 8); \ + S.bytes[(row) + 20] = (uint8_t)((value) >> 16); \ + S.bytes[(row) + 24] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#else +/* Index the bit-sliced state bytes in big-endian byte order */ +#define READ_ROW0() \ + (((uint32_t)(S.bytes[3])) | \ + (((uint32_t)(S.bytes[7])) << 8) | \ + (((uint32_t)(S.bytes[11])) << 16) | \ + (((uint32_t)(S.bytes[15])) << 24)) +#define READ_ROW1() \ + (((uint32_t)(S.bytes[2])) | \ + (((uint32_t)(S.bytes[6])) << 8) | \ + (((uint32_t)(S.bytes[10])) << 16) | \ + (((uint32_t)(S.bytes[14])) << 24)) +#define READ_ROW2() \ + (((uint32_t)(S.bytes[1])) | \ + (((uint32_t)(S.bytes[5])) << 8) | \ + (((uint32_t)(S.bytes[9])) << 16) | \ + (((uint32_t)(S.bytes[13])) << 24)) +#define READ_ROW3() \ + (((uint32_t)(S.bytes[0])) | \ + (((uint32_t)(S.bytes[4])) << 8) | \ + (((uint32_t)(S.bytes[8])) << 16) | \ + (((uint32_t)(S.bytes[12])) << 24)) +#define READ_ROW4() \ + (((uint32_t)(S.bytes[19])) | \ + (((uint32_t)(S.bytes[23])) << 8) | \ + (((uint32_t)(S.bytes[27])) << 16) | \ + (((uint32_t)(S.bytes[31])) << 24)) +#define READ_ROW5() \ + (((uint32_t)(S.bytes[18])) | \ + (((uint32_t)(S.bytes[22])) << 8) | \ + (((uint32_t)(S.bytes[26])) << 16) | \ + (((uint32_t)(S.bytes[30])) << 24)) +#define READ_ROW6() \ + (((uint32_t)(S.bytes[17])) | \ + (((uint32_t)(S.bytes[21])) << 8) | \ + (((uint32_t)(S.bytes[25])) << 16) | \ + (((uint32_t)(S.bytes[29])) << 24)) +#define READ_ROW7() \ + (((uint32_t)(S.bytes[16])) | \ + (((uint32_t)(S.bytes[20])) << 8) | \ + (((uint32_t)(S.bytes[24])) << 16) | \ + (((uint32_t)(S.bytes[28])) << 24)) +#define WRITE_ROW(row, value) \ + do { \ + if ((row) < 4) { \ + S.bytes[3 - (row)] = (uint8_t)(value); \ + S.bytes[7 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[11 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[15 - (row)] = (uint8_t)((value) >> 24); \ + } else { \ + S.bytes[20 - (row)] = (uint8_t)(value); \ + S.bytes[24 - (row)] = (uint8_t)((value) >> 8); \ + S.bytes[28 - (row)] = (uint8_t)((value) >> 16); \ + S.bytes[32 - (row)] = (uint8_t)((value) >> 24); \ + } \ + } while (0) +#endif + +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) +{ + union { + uint32_t words[PHOTON256_STATE_SIZE / 4]; + uint8_t bytes[PHOTON256_STATE_SIZE]; + } S; + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + uint8_t round; + + /* Convert the state into bit-sliced form */ + photon256_to_sliced(S.words, state); + + /* Perform all 12 permutation rounds */ + for (round = 0; round < PHOTON256_ROUNDS; ++round) { + /* Add the constants for this round */ + t0 = photon256_rc[round]; + S.words[0] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[1] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[2] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[3] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[4] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[5] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[6] ^= t0 & 0x01010101U; + t0 >>= 1; + S.words[7] ^= t0 & 0x01010101U; + + /* Apply the sbox to all nibbles in the state */ + photon256_sbox(S.words[0], S.words[1], S.words[2], S.words[3]); + photon256_sbox(S.words[4], S.words[5], S.words[6], S.words[7]); + + /* Rotate all rows left by the row number. + * + * We do this by applying permutations to the top and bottom words + * to rearrange the bits into the rotated form. Permutations + * generated with "http://programming.sirrida.de/calcperm.php". + * + * P_top = [0 1 2 3 4 5 6 7 15 8 9 10 11 12 13 14 22 23 + * 16 17 18 19 20 21 29 30 31 24 25 26 27 28] + * P_bot = [4 5 6 7 0 1 2 3 11 12 13 14 15 8 9 10 18 19 + * 20 21 22 23 16 17 25 26 27 28 29 30 31 24 + */ + #define TOP_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x07030100, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + #define BOTTOM_ROTATE_PERM(x) \ + do { \ + t1 = (x); \ + bit_permute_step(t1, 0x080c0e0f, 4); \ + bit_permute_step(t1, 0x22331100, 2); \ + bit_permute_step(t1, 0x55005500, 1); \ + (x) = t1; \ + } while (0) + TOP_ROTATE_PERM(S.words[0]); + TOP_ROTATE_PERM(S.words[1]); + TOP_ROTATE_PERM(S.words[2]); + TOP_ROTATE_PERM(S.words[3]); + BOTTOM_ROTATE_PERM(S.words[4]); + BOTTOM_ROTATE_PERM(S.words[5]); + BOTTOM_ROTATE_PERM(S.words[6]); + BOTTOM_ROTATE_PERM(S.words[7]); + + /* Mix the columns */ + #define MUL(a, x) (photon256_field_multiply((a), (x))) + t0 = READ_ROW0(); + t1 = READ_ROW1(); + t2 = READ_ROW2(); + t3 = READ_ROW3(); + t4 = READ_ROW4(); + t5 = READ_ROW5(); + t6 = READ_ROW6(); + t7 = READ_ROW7(); + t8 = MUL(0x02, t0) ^ MUL(0x04, t1) ^ MUL(0x02, t2) ^ MUL(0x0b, t3) ^ + MUL(0x02, t4) ^ MUL(0x08, t5) ^ MUL(0x05, t6) ^ MUL(0x06, t7); + WRITE_ROW(0, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x09, t1) ^ MUL(0x08, t2) ^ MUL(0x0d, t3) ^ + MUL(0x07, t4) ^ MUL(0x07, t5) ^ MUL(0x05, t6) ^ MUL(0x02, t7); + WRITE_ROW(1, t8); + t8 = MUL(0x04, t0) ^ MUL(0x04, t1) ^ MUL(0x0d, t2) ^ MUL(0x0d, t3) ^ + MUL(0x09, t4) ^ MUL(0x04, t5) ^ MUL(0x0d, t6) ^ MUL(0x09, t7); + WRITE_ROW(2, t8); + t8 = MUL(0x01, t0) ^ MUL(0x06, t1) ^ MUL(0x05, t2) ^ MUL(0x01, t3) ^ + MUL(0x0c, t4) ^ MUL(0x0d, t5) ^ MUL(0x0f, t6) ^ MUL(0x0e, t7); + WRITE_ROW(3, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x0c, t1) ^ MUL(0x09, t2) ^ MUL(0x0d, t3) ^ + MUL(0x0e, t4) ^ MUL(0x05, t5) ^ MUL(0x0e, t6) ^ MUL(0x0d, t7); + WRITE_ROW(4, t8); + t8 = MUL(0x09, t0) ^ MUL(0x0e, t1) ^ MUL(0x05, t2) ^ MUL(0x0f, t3) ^ + MUL(0x04, t4) ^ MUL(0x0c, t5) ^ MUL(0x09, t6) ^ MUL(0x06, t7); + WRITE_ROW(5, t8); + t8 = MUL(0x0c, t0) ^ MUL(0x02, t1) ^ MUL(0x02, t2) ^ MUL(0x0a, t3) ^ + MUL(0x03, t4) ^ MUL(0x01, t5) ^ MUL(0x01, t6) ^ MUL(0x0e, t7); + WRITE_ROW(6, t8); + t8 = MUL(0x0f, t0) ^ MUL(0x01, t1) ^ MUL(0x0d, t2) ^ MUL(0x0a, t3) ^ + MUL(0x05, t4) ^ MUL(0x0a, t5) ^ MUL(0x02, t6) ^ MUL(0x03, t7); + WRITE_ROW(7, t8); + } + + /* Convert back from bit-sliced form to regular form */ + photon256_from_sliced(state, S.bytes); +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.h new file mode 100644 index 0000000..ce8729a --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-photon256.h @@ -0,0 +1,54 @@ +/* + * 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_PHOTON256_H +#define LW_INTERNAL_PHOTON256_H + +/** + * \file internal-photon256.h + * \brief Internal implementation of the PHOTON-256 permutation. + * + * Warning: The current implementation of PHOTON-256 is constant-time + * but not constant-cache. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the PHOTON-256 permutation state in bytes. + */ +#define PHOTON256_STATE_SIZE 32 + +/** + * \brief Permutes the PHOTON-256 state. + * + * \param state The state to be permuted. + */ +void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-util.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.c b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.c new file mode 100644 index 0000000..f44bdad --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.c @@ -0,0 +1,451 @@ +/* + * 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 "photon-beetle.h" +#include "internal-photon256.h" +#include "internal-util.h" +#include + +aead_cipher_t const photon_beetle_128_cipher = { + "PHOTON-Beetle-AEAD-ENC-128", + PHOTON_BEETLE_KEY_SIZE, + PHOTON_BEETLE_NONCE_SIZE, + PHOTON_BEETLE_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + photon_beetle_128_aead_encrypt, + photon_beetle_128_aead_decrypt +}; + +aead_cipher_t const photon_beetle_32_cipher = { + "PHOTON-Beetle-AEAD-ENC-32", + PHOTON_BEETLE_KEY_SIZE, + PHOTON_BEETLE_NONCE_SIZE, + PHOTON_BEETLE_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + photon_beetle_32_aead_encrypt, + photon_beetle_32_aead_decrypt +}; + +aead_hash_algorithm_t const photon_beetle_hash_algorithm = { + "PHOTON-Beetle-HASH", + sizeof(int), + PHOTON_BEETLE_HASH_SIZE, + AEAD_FLAG_NONE, + photon_beetle_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 Rate of operation for PHOTON-Beetle-AEAD-ENC-128. + */ +#define PHOTON_BEETLE_128_RATE 16 + +/** + * \brief Rate of operation for PHOTON-Beetle-AEAD-ENC-32. + */ +#define PHOTON_BEETLE_32_RATE 4 + +/* Shifts a domain constant from the spec to the correct bit position */ +#define DOMAIN(c) ((c) << 5) + +/** + * \brief Processes the associated data for PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data, must be non-zero. + * \param rate Rate of absorption for the data. + * \param mempty Non-zero if the message is empty. + */ +static void photon_beetle_process_ad + (unsigned char state[PHOTON256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen, + unsigned rate, int mempty) +{ + unsigned temp; + + /* Absorb as many full rate blocks as possible */ + while (adlen > rate) { + photon256_permute(state); + lw_xor_block(state, ad, rate); + ad += rate; + adlen -= rate; + } + + /* Pad and absorb the last block */ + temp = (unsigned)adlen; + photon256_permute(state); + lw_xor_block(state, ad, temp); + if (temp < rate) + state[temp] ^= 0x01; /* padding */ + + /* Add the domain constant to finalize associated data processing */ + if (mempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(3); + else if (mempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(4); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +/** + * \brief Rotates part of the PHOTON-256 state right by one bit. + * + * \param out Output state buffer. + * \param in Input state buffer, must not overlap with \a out. + * \param len Length of the state buffer. + */ +static void photon_beetle_rotate1 + (unsigned char *out, const unsigned char *in, unsigned len) +{ + unsigned posn; + for (posn = 0; posn < (len - 1); ++posn) + out[posn] = (in[posn] >> 1) | (in[posn + 1] << 7); + out[len - 1] = (in[len - 1] >> 1) | (in[0] << 7); +} + +/** + * \brief Encrypts a plaintext block with PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Length of the message, must be non-zero. + * \param rate Rate of absorption for the data. + * \param adempty Non-zero if the associated data is empty. + */ +static void photon_beetle_encrypt + (unsigned char state[PHOTON256_STATE_SIZE], + unsigned char *c, const unsigned char *m, unsigned long long mlen, + unsigned rate, int adempty) +{ + unsigned char shuffle[PHOTON_BEETLE_128_RATE]; /* Block of max rate size */ + unsigned temp; + + /* Process all plaintext blocks except the last */ + while (mlen > rate) { + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + lw_xor_block(state, m, rate); + lw_xor_block_2_src(c, m, shuffle, rate); + c += rate; + m += rate; + mlen -= rate; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + if (temp == rate) { + lw_xor_block(state, m, rate); + lw_xor_block_2_src(c, m, shuffle, rate); + } else { + lw_xor_block(state, m, temp); + state[temp] ^= 0x01; /* padding */ + lw_xor_block_2_src(c, m, shuffle, temp); + } + + /* Add the domain constant to finalize message processing */ + if (adempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(5); + else if (adempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(6); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +/** + * \brief Decrypts a ciphertext block with PHOTON-Beetle. + * + * \param state PHOTON-256 permutation state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param mlen Length of the message, must be non-zero. + * \param rate Rate of absorption for the data. + * \param adempty Non-zero if the associated data is empty. + */ +static void photon_beetle_decrypt + (unsigned char state[PHOTON256_STATE_SIZE], + unsigned char *m, const unsigned char *c, unsigned long long mlen, + unsigned rate, int adempty) +{ + unsigned char shuffle[PHOTON_BEETLE_128_RATE]; /* Block of max rate size */ + unsigned temp; + + /* Process all plaintext blocks except the last */ + while (mlen > rate) { + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + lw_xor_block_2_src(m, c, shuffle, rate); + lw_xor_block(state, m, rate); + c += rate; + m += rate; + mlen -= rate; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + photon256_permute(state); + memcpy(shuffle, state + rate / 2, rate / 2); + photon_beetle_rotate1(shuffle + rate / 2, state, rate / 2); + if (temp == rate) { + lw_xor_block_2_src(m, c, shuffle, rate); + lw_xor_block(state, m, rate); + } else { + lw_xor_block_2_src(m, c, shuffle, temp); + lw_xor_block(state, m, temp); + state[temp] ^= 0x01; /* padding */ + } + + /* Add the domain constant to finalize message processing */ + if (adempty && temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(5); + else if (adempty) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(6); + else if (temp == rate) + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + else + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); +} + +int photon_beetle_128_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_128_RATE, mlen == 0); + } else if (mlen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + photon_beetle_encrypt + (state, c, m, mlen, PHOTON_BEETLE_128_RATE, adlen == 0); + } + + /* Generate the authentication tag */ + photon256_permute(state); + memcpy(c + mlen, state, PHOTON_BEETLE_TAG_SIZE); + return 0; +} + +int photon_beetle_128_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < PHOTON_BEETLE_TAG_SIZE) + return -1; + *mlen = clen - PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + clen -= PHOTON_BEETLE_TAG_SIZE; + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_128_RATE, clen == 0); + } else if (clen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + photon_beetle_decrypt + (state, m, c, clen, PHOTON_BEETLE_128_RATE, adlen == 0); + } + + /* Check the authentication tag */ + photon256_permute(state); + return aead_check_tag(m, clen, state, c + clen, PHOTON_BEETLE_TAG_SIZE); +} + +int photon_beetle_32_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_32_RATE, mlen == 0); + } else if (mlen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + photon_beetle_encrypt + (state, c, m, mlen, PHOTON_BEETLE_32_RATE, adlen == 0); + } + + /* Generate the authentication tag */ + photon256_permute(state); + memcpy(c + mlen, state, PHOTON_BEETLE_TAG_SIZE); + return 0; +} + +int photon_beetle_32_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) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < PHOTON_BEETLE_TAG_SIZE) + return -1; + *mlen = clen - PHOTON_BEETLE_TAG_SIZE; + + /* Initialize the state by concatenating the nonce and the key */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Process the associated data */ + clen -= PHOTON_BEETLE_TAG_SIZE; + if (adlen > 0) { + photon_beetle_process_ad + (state, ad, adlen, PHOTON_BEETLE_32_RATE, clen == 0); + } else if (clen == 0) { + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } + + /* Decrypt the ciphertext to produce the plaintext */ + if (clen > 0) { + photon_beetle_decrypt + (state, m, c, clen, PHOTON_BEETLE_32_RATE, adlen == 0); + } + + /* Check the authentication tag */ + photon256_permute(state); + return aead_check_tag(m, clen, state, c + clen, PHOTON_BEETLE_TAG_SIZE); +} + +int photon_beetle_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char state[PHOTON256_STATE_SIZE]; + unsigned temp; + + /* Absorb the input data */ + if (inlen == 0) { + /* No input data at all */ + memset(state, 0, sizeof(state) - 1); + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(1); + } else if (inlen <= PHOTON_BEETLE_128_RATE) { + /* Only one block of input data, which may require padding */ + temp = (unsigned)inlen; + memcpy(state, in, temp); + memset(state + temp, 0, sizeof(state) - temp - 1); + if (temp < PHOTON_BEETLE_128_RATE) { + state[temp] = 0x01; + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(1); + } else { + state[PHOTON256_STATE_SIZE - 1] = DOMAIN(2); + } + } else { + /* Initialize the state with the first block, then absorb the rest */ + memcpy(state, in, PHOTON_BEETLE_128_RATE); + memset(state + PHOTON_BEETLE_128_RATE, 0, + sizeof(state) - PHOTON_BEETLE_128_RATE); + in += PHOTON_BEETLE_128_RATE; + inlen -= PHOTON_BEETLE_128_RATE; + while (inlen > PHOTON_BEETLE_32_RATE) { + photon256_permute(state); + lw_xor_block(state, in, PHOTON_BEETLE_32_RATE); + in += PHOTON_BEETLE_32_RATE; + inlen -= PHOTON_BEETLE_32_RATE; + } + photon256_permute(state); + temp = (unsigned)inlen; + if (temp == PHOTON_BEETLE_32_RATE) { + lw_xor_block(state, in, PHOTON_BEETLE_32_RATE); + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(1); + } else { + lw_xor_block(state, in, temp); + state[temp] ^= 0x01; + state[PHOTON256_STATE_SIZE - 1] ^= DOMAIN(2); + } + } + + /* Generate the output hash */ + photon256_permute(state); + memcpy(out, state, 16); + photon256_permute(state); + memcpy(out + 16, state, 16); + return 0; +} diff --git a/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.h b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.h new file mode 100644 index 0000000..2d94a7e --- /dev/null +++ b/photon-beetle/Implementations/crypto_aead/photonbeetleaead128rate32v1/rhys/photon-beetle.h @@ -0,0 +1,224 @@ +/* + * 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_PHOTON_BEETLE_H +#define LWCRYPTO_PHOTON_BEETLE_H + +#include "aead-common.h" + +/** + * \file photon-beetle.h + * \brief PHOTON-Beetle authenticated encryption algorithm. + * + * PHOTON-Beetle is a family of authenticated encryption algorithms based + * on the PHOTON-256 permutation and using the Beetle sponge mode. + * There are three algorithms in the family: + * + * \li PHOTON-Beetle-AEAD-ENC-128 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag. Data is handled in 16 byte blocks. This is the primary + * member of the family for encryption. + * \li PHOTON-Beetle-AEAD-ENC-32 with a 128-bit key, a 128-bit nonce, and a + * 128-bit tag. Data is handled in 4 byte blocks. + * \li PHOTON-Beetle-Hash with a 256-bit hash output. The initial data is + * handled as a 16 byte block, and then the remaining bytes are processed + * in 4 byte blocks. + * + * References: https://www.isical.ac.in/~lightweight/beetle/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_TAG_SIZE 16 + +/** + * \brief Size of the nonce for PHOTON-Beetle. + */ +#define PHOTON_BEETLE_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for PHOTON-Beetle-HASH. + */ +#define PHOTON_BEETLE_HASH_SIZE 32 + +/** + * \brief Meta-information block for the PHOTON-Beetle-AEAD-ENC-128 cipher. + */ +extern aead_cipher_t const photon_beetle_128_cipher; + +/** + * \brief Meta-information block for the PHOTON-Beetle-AEAD-ENC-32 cipher. + */ +extern aead_cipher_t const photon_beetle_32_cipher; + +/** + * \brief Meta-information block for the PHOTON-Beetle-HASH algorithm. + */ +extern aead_hash_algorithm_t const photon_beetle_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa photon_beetle_128_aead_decrypt() + */ +int photon_beetle_128_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); + +/** + * \brief Decrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa photon_beetle_128_aead_encrypt() + */ +int photon_beetle_128_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); + +/** + * \brief Encrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-32. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa photon_beetle_32_aead_decrypt() + */ +int photon_beetle_32_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); + +/** + * \brief Decrypts and authenticates a packet with PHOTON-Beetle-AEAD-ENC-32. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa photon_beetle_32_aead_encrypt() + */ +int photon_beetle_32_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); + +/** + * \brief Hashes a block of input data with PHOTON-Beetle-HASH to + * generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * PHOTON_BEETLE_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 photon_beetle_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.c b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/api.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/encrypt.c b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/encrypt.c new file mode 100644 index 0000000..a63877d --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "pyjamask.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 pyjamask_128_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 pyjamask_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-ocb.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-ocb.h new file mode 100644 index 0000000..de544ba --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-ocb.h @@ -0,0 +1,335 @@ +/* + * 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_OCB_H +#define LW_INTERNAL_OCB_H + +#include "internal-util.h" +#include + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying block cipher: + * + * OCB_ALG_NAME Name of the algorithm that is using OCB mode. + * OCB_BLOCK_SIZE Size of the block for the underlying cipher in bytes. + * OCB_NONCE_SIZE Size of the nonce which must be < OCB_BLOCK_SIZE. + * OCB_TAG_SIZE Size of the authentication tag. + * OCB_KEY_SCHEDULE Type for the key schedule. + * OCB_SETUP_KEY Name of the key schedule setup function. + * OCB_ENCRYPT_BLOCK Name of the block cipher ECB encrypt function. + * OCB_DECRYPT_BLOCK Name of the block cipher ECB decrypt function. + * OCB_DOUBLE_L Name of the function to double L (optional). + */ +#if defined(OCB_ENCRYPT_BLOCK) + +/** + * \file internal-ocb.h + * \brief Internal implementation of the OCB block cipher mode. + * + * Note that OCB is covered by patents so it may not be usable in all + * applications. Open source applications should be covered, but for + * others you will need to contact the patent authors to find out + * if you can use it or if a paid license is required. + * + * License information: https://web.cs.ucdavis.edu/~rogaway/ocb/license.htm + * + * References: https://tools.ietf.org/html/rfc7253 + */ + +#define OCB_CONCAT_INNER(name,suffix) name##suffix +#define OCB_CONCAT(name,suffix) OCB_CONCAT_INNER(name,suffix) + +#if !defined(OCB_DOUBLE_L) + +#define OCB_DOUBLE_L OCB_CONCAT(OCB_ALG_NAME,_double_l) + +/* Double a value in GF(128) - default implementation */ +static void OCB_DOUBLE_L(unsigned char out[16], const unsigned char in[16]) +{ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)in[0]) >> 7); + for (index = 0; index < 15; ++index) + out[index] = (in[index] << 1) | (in[index + 1] >> 7); + out[15] = (in[15] << 1) ^ (mask & 0x87); +} + +#endif + +/* State information for OCB functions */ +#define OCB_STATE OCB_CONCAT(OCB_ALG_NAME,_state_t) +typedef struct +{ + OCB_KEY_SCHEDULE ks; + unsigned char Lstar[OCB_BLOCK_SIZE]; + unsigned char Ldollar[OCB_BLOCK_SIZE]; + unsigned char L0[OCB_BLOCK_SIZE]; + unsigned char L1[OCB_BLOCK_SIZE]; + +} OCB_STATE; + +/* Initializes the OCB state from the key and nonce */ +static void OCB_CONCAT(OCB_ALG_NAME,_init) + (OCB_STATE *state, const unsigned char *k, const unsigned char *nonce, + unsigned char offset[OCB_BLOCK_SIZE]) +{ + unsigned bottom; + + /* Set up the key schedule */ + OCB_SETUP_KEY(&(state->ks), k); + + /* Derive the values of L*, L$, L0, and L1 */ + memset(state->Lstar, 0, sizeof(state->Lstar)); + OCB_ENCRYPT_BLOCK(&(state->ks), state->Lstar, state->Lstar); + OCB_DOUBLE_L(state->Ldollar, state->Lstar); + OCB_DOUBLE_L(state->L0, state->Ldollar); + OCB_DOUBLE_L(state->L1, state->L0); + + /* Derive the initial offset from the nonce */ + memset(offset, 0, OCB_BLOCK_SIZE); + memcpy(offset + OCB_BLOCK_SIZE - OCB_NONCE_SIZE, nonce, OCB_NONCE_SIZE); + offset[0] = ((OCB_TAG_SIZE * 8) & 0x7F) << 1; + offset[OCB_BLOCK_SIZE - OCB_NONCE_SIZE - 1] |= 0x01; + bottom = offset[OCB_BLOCK_SIZE - 1] & 0x3F; + offset[OCB_BLOCK_SIZE - 1] &= 0xC0; + { + unsigned index; + unsigned byte_posn = bottom / 8; +#if OCB_BLOCK_SIZE == 16 + /* Standard OCB with a 128-bit block */ + unsigned char stretch[24]; + OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset); + memcpy(stretch + 16, stretch + 1, 8); + lw_xor_block(stretch + 16, stretch, 8); +#elif OCB_BLOCK_SIZE == 12 + /* 96-bit block handling from the Pyjamask specification */ + unsigned char stretch[20]; + OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset); + for (index = 0; index < 8; ++index) { + stretch[index + 12] = + (stretch[index + 1] << 1) | (stretch[index + 2] >> 7); + } + lw_xor_block(stretch + 12, stretch, 8); +#else + unsigned char stretch[OCB_BLOCK_SIZE + 8] = {0}; + #error "unsupported block size for OCB mode" +#endif + bottom %= 8; + if (bottom != 0) { + for (index = 0; index < OCB_BLOCK_SIZE; ++index) { + offset[index] = + (stretch[index + byte_posn] << bottom) | + (stretch[index + byte_posn + 1] >> (8 - bottom)); + } + } else { + memcpy(offset, stretch + byte_posn, OCB_BLOCK_SIZE); + } + } +} + +/* Calculate L_{ntz(i)} when the last two bits of i are zero */ +static void OCB_CONCAT(OCB_ALG_NAME,_calculate_L) + (OCB_STATE *state, unsigned char L[OCB_BLOCK_SIZE], unsigned long long i) +{ + OCB_DOUBLE_L(L, state->L1); + i >>= 2; + while ((i & 1) == 0) { + OCB_DOUBLE_L(L, L); + i >>= 1; + } +} + +/* Process associated data with OCB */ +static void OCB_CONCAT(OCB_ALG_NAME,_process_ad) + (OCB_STATE *state, unsigned char tag[OCB_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + + /* Process all full blocks */ + memset(offset, 0, sizeof(offset)); + block_number = 1; + while (adlen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state->L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state->L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block_2_src(block, offset, ad, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state->ks), block, block); + lw_xor_block(tag, block, OCB_BLOCK_SIZE); + ad += OCB_BLOCK_SIZE; + adlen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last partial block */ + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(offset, state->Lstar, OCB_BLOCK_SIZE); + lw_xor_block(offset, ad, temp); + offset[temp] ^= 0x80; + OCB_ENCRYPT_BLOCK(&(state->ks), block, offset); + lw_xor_block(tag, block, OCB_BLOCK_SIZE); + } +} + +int OCB_CONCAT(OCB_ALG_NAME,_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) +{ + OCB_STATE state; + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char sum[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + OCB_TAG_SIZE; + + /* Initialize the OCB state */ + OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset); + + /* Process all plaintext blocks except the last */ + memset(sum, 0, sizeof(sum)); + block_number = 1; + while (mlen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block(sum, m, OCB_BLOCK_SIZE); + lw_xor_block_2_src(block, offset, m, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, block); + lw_xor_block_2_src(c, block, offset, OCB_BLOCK_SIZE); + c += OCB_BLOCK_SIZE; + m += OCB_BLOCK_SIZE; + mlen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last plaintext block */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, offset); + lw_xor_block_2_src(c, block, m, temp); + c += temp; + } + + /* Finalize the encryption phase */ + lw_xor_block(sum, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum); + + /* Process the associated data and compute the final authentication tag */ + OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen); + memcpy(c, sum, OCB_TAG_SIZE); + return 0; +} + +int OCB_CONCAT(OCB_ALG_NAME,_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) +{ + OCB_STATE state; + unsigned char *mtemp = m; + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char sum[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < OCB_TAG_SIZE) + return -1; + *mlen = clen - OCB_TAG_SIZE; + + /* Initialize the OCB state */ + OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset); + + /* Process all ciphertext blocks except the last */ + memset(sum, 0, sizeof(sum)); + block_number = 1; + clen -= OCB_TAG_SIZE; + while (clen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block_2_src(block, offset, c, OCB_BLOCK_SIZE); + OCB_DECRYPT_BLOCK(&(state.ks), block, block); + lw_xor_block_2_src(m, block, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, m, OCB_BLOCK_SIZE); + c += OCB_BLOCK_SIZE; + m += OCB_BLOCK_SIZE; + clen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last ciphertext block */ + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, offset); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + c += temp; + } + + /* Finalize the decryption phase */ + lw_xor_block(sum, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum); + + /* Process the associated data and check the final authentication tag */ + OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen); + return aead_check_tag(mtemp, *mlen, sum, c, OCB_TAG_SIZE); +} + +#endif /* OCB_ENCRYPT_BLOCK */ + +#endif /* LW_INTERNAL_OCB_H */ diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.c b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.c new file mode 100644 index 0000000..f3a5655 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.c @@ -0,0 +1,305 @@ +/* + * 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 "internal-pyjamask.h" +#include "internal-util.h" + +/** + * \brief Performs a circulant binary matrix multiplication. + * + * \param x The matrix. + * \param y The vector to multiply with the matrix. + * + * \return The vector result of multiplying x by y. + */ +STATIC_INLINE uint32_t pyjamask_matrix_multiply(uint32_t x, uint32_t y) +{ + uint32_t result = 0; + int bit; + for (bit = 31; bit >= 0; --bit) { +#if defined(ESP32) + /* This version has slightly better performance on ESP32 */ + y = leftRotate1(y); + result ^= x & -(y & 1); + x = rightRotate1(x); +#else + result ^= x & -((y >> bit) & 1); + x = rightRotate1(x); +#endif + } + return result; +} + +void pyjamask_setup_key(pyjamask_key_schedule_t *ks, const unsigned char *key) +{ + uint32_t *rk = ks->k; + uint32_t k0, k1, k2, k3; + uint32_t temp; + uint8_t round; + + /* Load the words of the key */ + k0 = be_load_word32(key); + k1 = be_load_word32(key + 4); + k2 = be_load_word32(key + 8); + k3 = be_load_word32(key + 12); + + /* The first round key is the same as the key itself */ + rk[0] = k0; + rk[1] = k1; + rk[2] = k2; + rk[3] = k3; + rk += 4; + + /* Derive the round keys for all of the other rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Mix the columns */ + temp = k0 ^ k1 ^ k2 ^ k3; + k0 ^= temp; + k1 ^= temp; + k2 ^= temp; + k3 ^= temp; + + /* Mix the rows and add the round constants. Note that the Pyjamask + * specification says that k1/k2/k3 should be rotated left by 8, 15, + * and 18 bits. But the reference code actually rotates the words + * right. And the test vectors in the specification match up with + * right rotations, not left. We match the reference code here */ + k0 = pyjamask_matrix_multiply(0xb881b9caU, k0) ^ 0x00000080U ^ round; + k1 = rightRotate8(k1) ^ 0x00006a00U; + k2 = rightRotate15(k2) ^ 0x003f0000U; + k3 = rightRotate18(k3) ^ 0x24000000U; + + /* Write the round key to the schedule */ + rk[0] = k0; + rk[1] = k1; + rk[2] = k2; + rk[3] = k3; + } +} + +void pyjamask_128_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k; + uint32_t s0, s1, s2, s3; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + /* Apply the 128-bit Pyjamask sbox */ + s0 ^= s3; + s3 ^= s0 & s1; + s0 ^= s1 & s2; + s1 ^= s2 & s3; + s2 ^= s0 & s3; + s2 ^= s1; + s1 ^= s0; + s3 = ~s3; + s2 ^= s3; + s3 ^= s2; + s2 ^= s3; + + /* Mix the rows of the state */ + s0 = pyjamask_matrix_multiply(0xa3861085U, s0); + s1 = pyjamask_matrix_multiply(0x63417021U, s1); + s2 = pyjamask_matrix_multiply(0x692cf280U, s2); + s3 = pyjamask_matrix_multiply(0x48a54813U, s3); + } + + /* Mix in the key one last time */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void pyjamask_128_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k + 4 * PYJAMASK_ROUNDS; + uint32_t s0, s1, s2, s3; + uint8_t round; + + /* Load the ciphertext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Mix in the last round key */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + rk -= 4; + + /* Perform all decryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk -= 4) { + /* Inverse mix of the rows in the state */ + s0 = pyjamask_matrix_multiply(0x2037a121U, s0); + s1 = pyjamask_matrix_multiply(0x108ff2a0U, s1); + s2 = pyjamask_matrix_multiply(0x9054d8c0U, s2); + s3 = pyjamask_matrix_multiply(0x3354b117U, s3); + + /* Apply the inverse of the 128-bit Pyjamask sbox */ + s2 ^= s3; + s3 ^= s2; + s2 ^= s3; + s3 = ~s3; + s1 ^= s0; + s2 ^= s1; + s2 ^= s0 & s3; + s1 ^= s2 & s3; + s0 ^= s1 & s2; + s3 ^= s0 & s1; + s0 ^= s3; + + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + } + + /* Write the plaintext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void pyjamask_96_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k; + uint32_t s0, s1, s2; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + + /* Apply the 96-bit Pyjamask sbox */ + s0 ^= s1; + s1 ^= s2; + s2 ^= s0 & s1; + s0 ^= s1 & s2; + s1 ^= s0 & s2; + s2 ^= s0; + s2 = ~s2; + s1 ^= s0; + s0 ^= s1; + + /* Mix the rows of the state */ + s0 = pyjamask_matrix_multiply(0xa3861085U, s0); + s1 = pyjamask_matrix_multiply(0x63417021U, s1); + s2 = pyjamask_matrix_multiply(0x692cf280U, s2); + } + + /* Mix in the key one last time */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); +} + +void pyjamask_96_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k + 4 * PYJAMASK_ROUNDS; + uint32_t s0, s1, s2; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + + /* Mix in the last round key */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + rk -= 4; + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk -= 4) { + /* Inverse mix of the rows in the state */ + s0 = pyjamask_matrix_multiply(0x2037a121U, s0); + s1 = pyjamask_matrix_multiply(0x108ff2a0U, s1); + s2 = pyjamask_matrix_multiply(0x9054d8c0U, s2); + + /* Apply the inverse of the 96-bit Pyjamask sbox */ + s0 ^= s1; + s1 ^= s0; + s2 = ~s2; + s2 ^= s0; + s1 ^= s0 & s2; + s0 ^= s1 & s2; + s2 ^= s0 & s1; + s1 ^= s2; + s0 ^= s1; + + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + } + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.h new file mode 100644 index 0000000..3fd93a7 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-pyjamask.h @@ -0,0 +1,215 @@ +/* + * 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_PYJAMASK_H +#define LW_INTERNAL_PYJAMASK_H + +#include "internal-util.h" + +/** + * \file internal-pyjamask.h + * \brief Pyjamask block cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Number of rounds in the Pyjamask block cipher. + */ +#define PYJAMASK_ROUNDS 14 + +/** + * \brief Number of parallel states for masked operation. + */ +#define PYJAMASK_MASKING_ORDER 4 + +/** + * \brief Structure of the key schedule for Pyjamask block ciphers. + */ +typedef struct +{ + uint32_t k[(PYJAMASK_ROUNDS + 1) * 4]; /**< Words of the key schedule */ + +} pyjamask_key_schedule_t; + +/** + * \brief Structure of the key schedule for masked Pyjamask block ciphers. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[PYJAMASK_MASKING_ORDER * (PYJAMASK_ROUNDS + 1) * 4]; + +} pyjamask_masked_key_schedule_t; + +/** + * \brief Sets up the key schedule for the Pyjamask block cipher. + * + * \param ks The key schedule on output. + * \param key The 16 bytes of the key on input. + */ +void pyjamask_setup_key(pyjamask_key_schedule_t *ks, const unsigned char *key); + +/** + * \brief Encrypts a 128-bit block with Pyjamask-128. + * + * \param ks Points to the 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. + * + * \sa pyjamask_128_decrypt() + */ +void pyjamask_128_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with Pyjamask-128. + * + * \param ks Points to the 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 decryption. + * + * \sa pyjamask_128_encrypt() + */ +void pyjamask_128_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 96-bit block with Pyjamask-96. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \sa pyjamask_96_decrypt() + */ +void pyjamask_96_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 96-bit block with Pyjamask-96. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + * + * \sa pyjamask_96_encrypt() + */ +void pyjamask_96_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Sets up the key schedule for the masked Pyjamask block cipher. + * + * \param ks The key schedule on output. + * \param key The 16 bytes of the key on input. + */ +void pyjamask_masked_setup_key + (pyjamask_masked_key_schedule_t *ks, const unsigned char *key); + +/** + * \brief Encrypts a 128-bit block with Pyjamask-128 in masked mode. + * + * \param ks Points to the 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. + * + * \sa pyjamask_masked_128_decrypt() + */ +void pyjamask_masked_128_encrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with Pyjamask-128 in masked mode. + * + * \param ks Points to the 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 decryption. + * + * \sa pyjamask_masked_128_encrypt() + */ +void pyjamask_masked_128_decrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 96-bit block with Pyjamask-96 in masked mode. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \sa pyjamask_masked_96_decrypt() + */ +void pyjamask_masked_96_encrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 96-bit block with Pyjamask-96 in masked mode. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + * + * \sa pyjamask_masked_96_encrypt() + */ +void pyjamask_masked_96_decrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-util.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask-128.c b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask-128.c new file mode 100644 index 0000000..a70a32f --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask-128.c @@ -0,0 +1,44 @@ +/* + * 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 "pyjamask.h" +#include "internal-pyjamask.h" + +aead_cipher_t const pyjamask_128_cipher = { + "Pyjamask-128-AEAD", + PYJAMASK_128_KEY_SIZE, + PYJAMASK_128_NONCE_SIZE, + PYJAMASK_128_TAG_SIZE, + AEAD_FLAG_NONE, + pyjamask_128_aead_encrypt, + pyjamask_128_aead_decrypt +}; + +#define OCB_ALG_NAME pyjamask_128 +#define OCB_BLOCK_SIZE 16 +#define OCB_NONCE_SIZE PYJAMASK_128_NONCE_SIZE +#define OCB_TAG_SIZE PYJAMASK_128_TAG_SIZE +#define OCB_KEY_SCHEDULE pyjamask_key_schedule_t +#define OCB_SETUP_KEY pyjamask_setup_key +#define OCB_ENCRYPT_BLOCK pyjamask_128_encrypt +#define OCB_DECRYPT_BLOCK pyjamask_128_decrypt +#include "internal-ocb.h" diff --git a/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask.h b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask.h new file mode 100644 index 0000000..23ec744 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask128aeadv1/rhys/pyjamask.h @@ -0,0 +1,335 @@ +/* + * 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_PYJAMASK_H +#define LWCRYPTO_PYJAMASK_H + +#include "aead-common.h" + +/** + * \file pyjamask.h + * \brief Pyjamask authenticated encryption algorithm. + * + * Pyjamask AEAD is a family of authenticated encryption algorithms that are + * built around the Pyjamask-128 and Pyjamask-96 block ciphers in OCB mode. + * Pyjamask-128-AEAD has a 128-bit key, a 96-bit nonce, and a 128-bit + * authentication tag. Pyjamask-96-AEAD has a 128-bit key, a 64-bit nonce, + * and a 96-bit authentication tag. + * + * References: https://pyjamask-cipher.github.io/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_NONCE_SIZE 12 + +/** + * \brief Size of the key for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_TAG_SIZE 12 + +/** + * \brief Size of the nonce for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_NONCE_SIZE 8 + +/** + * \brief Meta-information block for the Pyjamask-128-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_128_cipher; + +/** + * \brief Meta-information block for the Pyjamask-96-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_96_cipher; + +/** + * \brief Meta-information block for the masked Pyjamask-128-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_masked_128_cipher; + +/** + * \brief Meta-information block for the masked Pyjamask-96-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_masked_96_cipher; + +/** + * \brief Encrypts and authenticates a packet with Pyjamask-128-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_128_aead_decrypt() + */ +int pyjamask_128_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); + +/** + * \brief Decrypts and authenticates a packet with Pyjamask-128-AEAD. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_128_aead_encrypt() + */ +int pyjamask_128_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); + +/** + * \brief Encrypts and authenticates a packet with Pyjamask-96-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_96_aead_decrypt() + */ +int pyjamask_96_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); + +/** + * \brief Decrypts and authenticates a packet with Pyjamask-96-AEAD. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_96_aead_encrypt() + */ +int pyjamask_96_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); + +/** + * \brief Encrypts and authenticates a packet with masked Pyjamask-128-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_masked_128_aead_decrypt() + */ +int pyjamask_masked_128_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); + +/** + * \brief Decrypts and authenticates a packet with masked Pyjamask-128-AEAD. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_masked_128_aead_encrypt() + */ +int pyjamask_masked_128_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); + +/** + * \brief Encrypts and authenticates a packet with masked Pyjamask-96-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_masked_96_aead_decrypt() + */ +int pyjamask_masked_96_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); + +/** + * \brief Decrypts and authenticates a packet with masked Pyjamask-96-AEAD. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_masked_96_aead_encrypt() + */ +int pyjamask_masked_96_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.c b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/api.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/api.h new file mode 100644 index 0000000..bd8cdcb --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 8 +#define CRYPTO_ABYTES 12 +#define CRYPTO_NOOVERLAP 1 diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/encrypt.c b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/encrypt.c new file mode 100644 index 0000000..f09b0ed --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "pyjamask.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 pyjamask_96_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 pyjamask_96_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-ocb.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-ocb.h new file mode 100644 index 0000000..de544ba --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-ocb.h @@ -0,0 +1,335 @@ +/* + * 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_OCB_H +#define LW_INTERNAL_OCB_H + +#include "internal-util.h" +#include + +/* We expect a number of macros to be defined before this file + * is included to configure the underlying block cipher: + * + * OCB_ALG_NAME Name of the algorithm that is using OCB mode. + * OCB_BLOCK_SIZE Size of the block for the underlying cipher in bytes. + * OCB_NONCE_SIZE Size of the nonce which must be < OCB_BLOCK_SIZE. + * OCB_TAG_SIZE Size of the authentication tag. + * OCB_KEY_SCHEDULE Type for the key schedule. + * OCB_SETUP_KEY Name of the key schedule setup function. + * OCB_ENCRYPT_BLOCK Name of the block cipher ECB encrypt function. + * OCB_DECRYPT_BLOCK Name of the block cipher ECB decrypt function. + * OCB_DOUBLE_L Name of the function to double L (optional). + */ +#if defined(OCB_ENCRYPT_BLOCK) + +/** + * \file internal-ocb.h + * \brief Internal implementation of the OCB block cipher mode. + * + * Note that OCB is covered by patents so it may not be usable in all + * applications. Open source applications should be covered, but for + * others you will need to contact the patent authors to find out + * if you can use it or if a paid license is required. + * + * License information: https://web.cs.ucdavis.edu/~rogaway/ocb/license.htm + * + * References: https://tools.ietf.org/html/rfc7253 + */ + +#define OCB_CONCAT_INNER(name,suffix) name##suffix +#define OCB_CONCAT(name,suffix) OCB_CONCAT_INNER(name,suffix) + +#if !defined(OCB_DOUBLE_L) + +#define OCB_DOUBLE_L OCB_CONCAT(OCB_ALG_NAME,_double_l) + +/* Double a value in GF(128) - default implementation */ +static void OCB_DOUBLE_L(unsigned char out[16], const unsigned char in[16]) +{ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)in[0]) >> 7); + for (index = 0; index < 15; ++index) + out[index] = (in[index] << 1) | (in[index + 1] >> 7); + out[15] = (in[15] << 1) ^ (mask & 0x87); +} + +#endif + +/* State information for OCB functions */ +#define OCB_STATE OCB_CONCAT(OCB_ALG_NAME,_state_t) +typedef struct +{ + OCB_KEY_SCHEDULE ks; + unsigned char Lstar[OCB_BLOCK_SIZE]; + unsigned char Ldollar[OCB_BLOCK_SIZE]; + unsigned char L0[OCB_BLOCK_SIZE]; + unsigned char L1[OCB_BLOCK_SIZE]; + +} OCB_STATE; + +/* Initializes the OCB state from the key and nonce */ +static void OCB_CONCAT(OCB_ALG_NAME,_init) + (OCB_STATE *state, const unsigned char *k, const unsigned char *nonce, + unsigned char offset[OCB_BLOCK_SIZE]) +{ + unsigned bottom; + + /* Set up the key schedule */ + OCB_SETUP_KEY(&(state->ks), k); + + /* Derive the values of L*, L$, L0, and L1 */ + memset(state->Lstar, 0, sizeof(state->Lstar)); + OCB_ENCRYPT_BLOCK(&(state->ks), state->Lstar, state->Lstar); + OCB_DOUBLE_L(state->Ldollar, state->Lstar); + OCB_DOUBLE_L(state->L0, state->Ldollar); + OCB_DOUBLE_L(state->L1, state->L0); + + /* Derive the initial offset from the nonce */ + memset(offset, 0, OCB_BLOCK_SIZE); + memcpy(offset + OCB_BLOCK_SIZE - OCB_NONCE_SIZE, nonce, OCB_NONCE_SIZE); + offset[0] = ((OCB_TAG_SIZE * 8) & 0x7F) << 1; + offset[OCB_BLOCK_SIZE - OCB_NONCE_SIZE - 1] |= 0x01; + bottom = offset[OCB_BLOCK_SIZE - 1] & 0x3F; + offset[OCB_BLOCK_SIZE - 1] &= 0xC0; + { + unsigned index; + unsigned byte_posn = bottom / 8; +#if OCB_BLOCK_SIZE == 16 + /* Standard OCB with a 128-bit block */ + unsigned char stretch[24]; + OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset); + memcpy(stretch + 16, stretch + 1, 8); + lw_xor_block(stretch + 16, stretch, 8); +#elif OCB_BLOCK_SIZE == 12 + /* 96-bit block handling from the Pyjamask specification */ + unsigned char stretch[20]; + OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset); + for (index = 0; index < 8; ++index) { + stretch[index + 12] = + (stretch[index + 1] << 1) | (stretch[index + 2] >> 7); + } + lw_xor_block(stretch + 12, stretch, 8); +#else + unsigned char stretch[OCB_BLOCK_SIZE + 8] = {0}; + #error "unsupported block size for OCB mode" +#endif + bottom %= 8; + if (bottom != 0) { + for (index = 0; index < OCB_BLOCK_SIZE; ++index) { + offset[index] = + (stretch[index + byte_posn] << bottom) | + (stretch[index + byte_posn + 1] >> (8 - bottom)); + } + } else { + memcpy(offset, stretch + byte_posn, OCB_BLOCK_SIZE); + } + } +} + +/* Calculate L_{ntz(i)} when the last two bits of i are zero */ +static void OCB_CONCAT(OCB_ALG_NAME,_calculate_L) + (OCB_STATE *state, unsigned char L[OCB_BLOCK_SIZE], unsigned long long i) +{ + OCB_DOUBLE_L(L, state->L1); + i >>= 2; + while ((i & 1) == 0) { + OCB_DOUBLE_L(L, L); + i >>= 1; + } +} + +/* Process associated data with OCB */ +static void OCB_CONCAT(OCB_ALG_NAME,_process_ad) + (OCB_STATE *state, unsigned char tag[OCB_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + + /* Process all full blocks */ + memset(offset, 0, sizeof(offset)); + block_number = 1; + while (adlen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state->L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state->L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block_2_src(block, offset, ad, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state->ks), block, block); + lw_xor_block(tag, block, OCB_BLOCK_SIZE); + ad += OCB_BLOCK_SIZE; + adlen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last partial block */ + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(offset, state->Lstar, OCB_BLOCK_SIZE); + lw_xor_block(offset, ad, temp); + offset[temp] ^= 0x80; + OCB_ENCRYPT_BLOCK(&(state->ks), block, offset); + lw_xor_block(tag, block, OCB_BLOCK_SIZE); + } +} + +int OCB_CONCAT(OCB_ALG_NAME,_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) +{ + OCB_STATE state; + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char sum[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + OCB_TAG_SIZE; + + /* Initialize the OCB state */ + OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset); + + /* Process all plaintext blocks except the last */ + memset(sum, 0, sizeof(sum)); + block_number = 1; + while (mlen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block(sum, m, OCB_BLOCK_SIZE); + lw_xor_block_2_src(block, offset, m, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, block); + lw_xor_block_2_src(c, block, offset, OCB_BLOCK_SIZE); + c += OCB_BLOCK_SIZE; + m += OCB_BLOCK_SIZE; + mlen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last plaintext block */ + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, offset); + lw_xor_block_2_src(c, block, m, temp); + c += temp; + } + + /* Finalize the encryption phase */ + lw_xor_block(sum, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum); + + /* Process the associated data and compute the final authentication tag */ + OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen); + memcpy(c, sum, OCB_TAG_SIZE); + return 0; +} + +int OCB_CONCAT(OCB_ALG_NAME,_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) +{ + OCB_STATE state; + unsigned char *mtemp = m; + unsigned char offset[OCB_BLOCK_SIZE]; + unsigned char sum[OCB_BLOCK_SIZE]; + unsigned char block[OCB_BLOCK_SIZE]; + unsigned long long block_number; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < OCB_TAG_SIZE) + return -1; + *mlen = clen - OCB_TAG_SIZE; + + /* Initialize the OCB state */ + OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset); + + /* Process all ciphertext blocks except the last */ + memset(sum, 0, sizeof(sum)); + block_number = 1; + clen -= OCB_TAG_SIZE; + while (clen >= OCB_BLOCK_SIZE) { + if (block_number & 1) { + lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE); + } else if ((block_number & 3) == 2) { + lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE); + } else { + OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number); + lw_xor_block(offset, block, OCB_BLOCK_SIZE); + } + lw_xor_block_2_src(block, offset, c, OCB_BLOCK_SIZE); + OCB_DECRYPT_BLOCK(&(state.ks), block, block); + lw_xor_block_2_src(m, block, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, m, OCB_BLOCK_SIZE); + c += OCB_BLOCK_SIZE; + m += OCB_BLOCK_SIZE; + clen -= OCB_BLOCK_SIZE; + ++block_number; + } + + /* Pad and process the last ciphertext block */ + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), block, offset); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + c += temp; + } + + /* Finalize the decryption phase */ + lw_xor_block(sum, offset, OCB_BLOCK_SIZE); + lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE); + OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum); + + /* Process the associated data and check the final authentication tag */ + OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen); + return aead_check_tag(mtemp, *mlen, sum, c, OCB_TAG_SIZE); +} + +#endif /* OCB_ENCRYPT_BLOCK */ + +#endif /* LW_INTERNAL_OCB_H */ diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.c b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.c new file mode 100644 index 0000000..f3a5655 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.c @@ -0,0 +1,305 @@ +/* + * 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 "internal-pyjamask.h" +#include "internal-util.h" + +/** + * \brief Performs a circulant binary matrix multiplication. + * + * \param x The matrix. + * \param y The vector to multiply with the matrix. + * + * \return The vector result of multiplying x by y. + */ +STATIC_INLINE uint32_t pyjamask_matrix_multiply(uint32_t x, uint32_t y) +{ + uint32_t result = 0; + int bit; + for (bit = 31; bit >= 0; --bit) { +#if defined(ESP32) + /* This version has slightly better performance on ESP32 */ + y = leftRotate1(y); + result ^= x & -(y & 1); + x = rightRotate1(x); +#else + result ^= x & -((y >> bit) & 1); + x = rightRotate1(x); +#endif + } + return result; +} + +void pyjamask_setup_key(pyjamask_key_schedule_t *ks, const unsigned char *key) +{ + uint32_t *rk = ks->k; + uint32_t k0, k1, k2, k3; + uint32_t temp; + uint8_t round; + + /* Load the words of the key */ + k0 = be_load_word32(key); + k1 = be_load_word32(key + 4); + k2 = be_load_word32(key + 8); + k3 = be_load_word32(key + 12); + + /* The first round key is the same as the key itself */ + rk[0] = k0; + rk[1] = k1; + rk[2] = k2; + rk[3] = k3; + rk += 4; + + /* Derive the round keys for all of the other rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Mix the columns */ + temp = k0 ^ k1 ^ k2 ^ k3; + k0 ^= temp; + k1 ^= temp; + k2 ^= temp; + k3 ^= temp; + + /* Mix the rows and add the round constants. Note that the Pyjamask + * specification says that k1/k2/k3 should be rotated left by 8, 15, + * and 18 bits. But the reference code actually rotates the words + * right. And the test vectors in the specification match up with + * right rotations, not left. We match the reference code here */ + k0 = pyjamask_matrix_multiply(0xb881b9caU, k0) ^ 0x00000080U ^ round; + k1 = rightRotate8(k1) ^ 0x00006a00U; + k2 = rightRotate15(k2) ^ 0x003f0000U; + k3 = rightRotate18(k3) ^ 0x24000000U; + + /* Write the round key to the schedule */ + rk[0] = k0; + rk[1] = k1; + rk[2] = k2; + rk[3] = k3; + } +} + +void pyjamask_128_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k; + uint32_t s0, s1, s2, s3; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + /* Apply the 128-bit Pyjamask sbox */ + s0 ^= s3; + s3 ^= s0 & s1; + s0 ^= s1 & s2; + s1 ^= s2 & s3; + s2 ^= s0 & s3; + s2 ^= s1; + s1 ^= s0; + s3 = ~s3; + s2 ^= s3; + s3 ^= s2; + s2 ^= s3; + + /* Mix the rows of the state */ + s0 = pyjamask_matrix_multiply(0xa3861085U, s0); + s1 = pyjamask_matrix_multiply(0x63417021U, s1); + s2 = pyjamask_matrix_multiply(0x692cf280U, s2); + s3 = pyjamask_matrix_multiply(0x48a54813U, s3); + } + + /* Mix in the key one last time */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void pyjamask_128_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k + 4 * PYJAMASK_ROUNDS; + uint32_t s0, s1, s2, s3; + uint8_t round; + + /* Load the ciphertext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Mix in the last round key */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + rk -= 4; + + /* Perform all decryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk -= 4) { + /* Inverse mix of the rows in the state */ + s0 = pyjamask_matrix_multiply(0x2037a121U, s0); + s1 = pyjamask_matrix_multiply(0x108ff2a0U, s1); + s2 = pyjamask_matrix_multiply(0x9054d8c0U, s2); + s3 = pyjamask_matrix_multiply(0x3354b117U, s3); + + /* Apply the inverse of the 128-bit Pyjamask sbox */ + s2 ^= s3; + s3 ^= s2; + s2 ^= s3; + s3 = ~s3; + s1 ^= s0; + s2 ^= s1; + s2 ^= s0 & s3; + s1 ^= s2 & s3; + s0 ^= s1 & s2; + s3 ^= s0 & s1; + s0 ^= s3; + + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + } + + /* Write the plaintext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void pyjamask_96_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k; + uint32_t s0, s1, s2; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk += 4) { + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + + /* Apply the 96-bit Pyjamask sbox */ + s0 ^= s1; + s1 ^= s2; + s2 ^= s0 & s1; + s0 ^= s1 & s2; + s1 ^= s0 & s2; + s2 ^= s0; + s2 = ~s2; + s1 ^= s0; + s0 ^= s1; + + /* Mix the rows of the state */ + s0 = pyjamask_matrix_multiply(0xa3861085U, s0); + s1 = pyjamask_matrix_multiply(0x63417021U, s1); + s2 = pyjamask_matrix_multiply(0x692cf280U, s2); + } + + /* Mix in the key one last time */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); +} + +void pyjamask_96_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + const uint32_t *rk = ks->k + 4 * PYJAMASK_ROUNDS; + uint32_t s0, s1, s2; + uint8_t round; + + /* Load the plaintext from the input buffer */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + + /* Mix in the last round key */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + rk -= 4; + + /* Perform all encryption rounds */ + for (round = 0; round < PYJAMASK_ROUNDS; ++round, rk -= 4) { + /* Inverse mix of the rows in the state */ + s0 = pyjamask_matrix_multiply(0x2037a121U, s0); + s1 = pyjamask_matrix_multiply(0x108ff2a0U, s1); + s2 = pyjamask_matrix_multiply(0x9054d8c0U, s2); + + /* Apply the inverse of the 96-bit Pyjamask sbox */ + s0 ^= s1; + s1 ^= s0; + s2 = ~s2; + s2 ^= s0; + s1 ^= s0 & s2; + s0 ^= s1 & s2; + s2 ^= s0 & s1; + s1 ^= s2; + s0 ^= s1; + + /* Add the round key to the state */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + } + + /* Write the ciphertext to the output buffer */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); +} diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.h new file mode 100644 index 0000000..3fd93a7 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-pyjamask.h @@ -0,0 +1,215 @@ +/* + * 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_PYJAMASK_H +#define LW_INTERNAL_PYJAMASK_H + +#include "internal-util.h" + +/** + * \file internal-pyjamask.h + * \brief Pyjamask block cipher. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Number of rounds in the Pyjamask block cipher. + */ +#define PYJAMASK_ROUNDS 14 + +/** + * \brief Number of parallel states for masked operation. + */ +#define PYJAMASK_MASKING_ORDER 4 + +/** + * \brief Structure of the key schedule for Pyjamask block ciphers. + */ +typedef struct +{ + uint32_t k[(PYJAMASK_ROUNDS + 1) * 4]; /**< Words of the key schedule */ + +} pyjamask_key_schedule_t; + +/** + * \brief Structure of the key schedule for masked Pyjamask block ciphers. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[PYJAMASK_MASKING_ORDER * (PYJAMASK_ROUNDS + 1) * 4]; + +} pyjamask_masked_key_schedule_t; + +/** + * \brief Sets up the key schedule for the Pyjamask block cipher. + * + * \param ks The key schedule on output. + * \param key The 16 bytes of the key on input. + */ +void pyjamask_setup_key(pyjamask_key_schedule_t *ks, const unsigned char *key); + +/** + * \brief Encrypts a 128-bit block with Pyjamask-128. + * + * \param ks Points to the 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. + * + * \sa pyjamask_128_decrypt() + */ +void pyjamask_128_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with Pyjamask-128. + * + * \param ks Points to the 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 decryption. + * + * \sa pyjamask_128_encrypt() + */ +void pyjamask_128_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 96-bit block with Pyjamask-96. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \sa pyjamask_96_decrypt() + */ +void pyjamask_96_encrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 96-bit block with Pyjamask-96. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + * + * \sa pyjamask_96_encrypt() + */ +void pyjamask_96_decrypt + (const pyjamask_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Sets up the key schedule for the masked Pyjamask block cipher. + * + * \param ks The key schedule on output. + * \param key The 16 bytes of the key on input. + */ +void pyjamask_masked_setup_key + (pyjamask_masked_key_schedule_t *ks, const unsigned char *key); + +/** + * \brief Encrypts a 128-bit block with Pyjamask-128 in masked mode. + * + * \param ks Points to the 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. + * + * \sa pyjamask_masked_128_decrypt() + */ +void pyjamask_masked_128_encrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with Pyjamask-128 in masked mode. + * + * \param ks Points to the 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 decryption. + * + * \sa pyjamask_masked_128_encrypt() + */ +void pyjamask_masked_128_decrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 96-bit block with Pyjamask-96 in masked mode. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * \sa pyjamask_masked_96_decrypt() + */ +void pyjamask_masked_96_encrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 96-bit block with Pyjamask-96 in masked mode. + * + * \param ks Points to the key schedule. + * \param output Output buffer which must be at least 12 bytes in length. + * \param input Input buffer which must be at least 12 bytes in length. + * + * The \a input and \a output buffers can be the same buffer for + * in-place decryption. + * + * \sa pyjamask_masked_96_encrypt() + */ +void pyjamask_masked_96_decrypt + (const pyjamask_masked_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-util.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask-96.c b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask-96.c new file mode 100644 index 0000000..3361699 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask-96.c @@ -0,0 +1,57 @@ +/* + * 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 "pyjamask.h" +#include "internal-pyjamask.h" + +aead_cipher_t const pyjamask_96_cipher = { + "Pyjamask-96-AEAD", + PYJAMASK_96_KEY_SIZE, + PYJAMASK_96_NONCE_SIZE, + PYJAMASK_96_TAG_SIZE, + AEAD_FLAG_NONE, + pyjamask_96_aead_encrypt, + pyjamask_96_aead_decrypt +}; + +/* Double a value in GF(96) */ +static void pyjamask_96_double_l + (unsigned char out[12], const unsigned char in[12]) +{ + unsigned index; + unsigned char mask = (unsigned char)(((signed char)in[0]) >> 7); + for (index = 0; index < 11; ++index) + out[index] = (in[index] << 1) | (in[index + 1] >> 7); + out[11] = (in[11] << 1) ^ (mask & 0x41); + out[10] ^= (mask & 0x06); +} + +#define OCB_ALG_NAME pyjamask_96 +#define OCB_BLOCK_SIZE 12 +#define OCB_NONCE_SIZE PYJAMASK_96_NONCE_SIZE +#define OCB_TAG_SIZE PYJAMASK_96_TAG_SIZE +#define OCB_KEY_SCHEDULE pyjamask_key_schedule_t +#define OCB_SETUP_KEY pyjamask_setup_key +#define OCB_ENCRYPT_BLOCK pyjamask_96_encrypt +#define OCB_DECRYPT_BLOCK pyjamask_96_decrypt +#define OCB_DOUBLE_L pyjamask_96_double_l +#include "internal-ocb.h" diff --git a/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask.h b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask.h new file mode 100644 index 0000000..23ec744 --- /dev/null +++ b/pyjamask/Implementations/crypto_aead/pyjamask96aeadv1/rhys/pyjamask.h @@ -0,0 +1,335 @@ +/* + * 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_PYJAMASK_H +#define LWCRYPTO_PYJAMASK_H + +#include "aead-common.h" + +/** + * \file pyjamask.h + * \brief Pyjamask authenticated encryption algorithm. + * + * Pyjamask AEAD is a family of authenticated encryption algorithms that are + * built around the Pyjamask-128 and Pyjamask-96 block ciphers in OCB mode. + * Pyjamask-128-AEAD has a 128-bit key, a 96-bit nonce, and a 128-bit + * authentication tag. Pyjamask-96-AEAD has a 128-bit key, a 64-bit nonce, + * and a 96-bit authentication tag. + * + * References: https://pyjamask-cipher.github.io/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Pyjamask-128-AEAD. + */ +#define PYJAMASK_128_NONCE_SIZE 12 + +/** + * \brief Size of the key for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_TAG_SIZE 12 + +/** + * \brief Size of the nonce for Pyjamask-96-AEAD. + */ +#define PYJAMASK_96_NONCE_SIZE 8 + +/** + * \brief Meta-information block for the Pyjamask-128-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_128_cipher; + +/** + * \brief Meta-information block for the Pyjamask-96-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_96_cipher; + +/** + * \brief Meta-information block for the masked Pyjamask-128-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_masked_128_cipher; + +/** + * \brief Meta-information block for the masked Pyjamask-96-AEAD cipher. + */ +extern aead_cipher_t const pyjamask_masked_96_cipher; + +/** + * \brief Encrypts and authenticates a packet with Pyjamask-128-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_128_aead_decrypt() + */ +int pyjamask_128_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); + +/** + * \brief Decrypts and authenticates a packet with Pyjamask-128-AEAD. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_128_aead_encrypt() + */ +int pyjamask_128_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); + +/** + * \brief Encrypts and authenticates a packet with Pyjamask-96-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_96_aead_decrypt() + */ +int pyjamask_96_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); + +/** + * \brief Decrypts and authenticates a packet with Pyjamask-96-AEAD. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_96_aead_encrypt() + */ +int pyjamask_96_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); + +/** + * \brief Encrypts and authenticates a packet with masked Pyjamask-128-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_masked_128_aead_decrypt() + */ +int pyjamask_masked_128_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); + +/** + * \brief Decrypts and authenticates a packet with masked Pyjamask-128-AEAD. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_masked_128_aead_encrypt() + */ +int pyjamask_masked_128_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); + +/** + * \brief Encrypts and authenticates a packet with masked Pyjamask-96-AEAD. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 12 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa pyjamask_masked_96_aead_decrypt() + */ +int pyjamask_masked_96_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); + +/** + * \brief Decrypts and authenticates a packet with masked Pyjamask-96-AEAD. + * + * \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 - not used by this algorithm. + * \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 12 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa pyjamask_masked_96_aead_encrypt() + */ +int pyjamask_masked_96_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/encrypt.c new file mode 100644 index 0000000..f13a728 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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); +} diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm1v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/encrypt.c new file mode 100644 index 0000000..520d992 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m2_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_m2_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm2v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/encrypt.c new file mode 100644 index 0000000..7e0c676 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m3_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_m3_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusm3v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/encrypt.c new file mode 100644 index 0000000..444a0c6 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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); +} diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn1v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/encrypt.c new file mode 100644 index 0000000..275a53c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_n2_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_n2_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn2v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.c b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/api.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/encrypt.c b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/encrypt.c new file mode 100644 index 0000000..a522291 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_n3_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_n3_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.c b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinnyutil.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-util.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.c b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.c new file mode 100644 index 0000000..be1c0fa --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.c @@ -0,0 +1,1963 @@ +/* + * 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 "romulus.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const romulus_n1_cipher = { + "Romulus-N1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n1_aead_encrypt, + romulus_n1_aead_decrypt +}; + +aead_cipher_t const romulus_n2_cipher = { + "Romulus-N2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n2_aead_encrypt, + romulus_n2_aead_decrypt +}; + +aead_cipher_t const romulus_n3_cipher = { + "Romulus-N3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_n3_aead_encrypt, + romulus_n3_aead_decrypt +}; + +aead_cipher_t const romulus_m1_cipher = { + "Romulus-M1", + ROMULUS_KEY_SIZE, + ROMULUS1_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m1_aead_encrypt, + romulus_m1_aead_decrypt +}; + +aead_cipher_t const romulus_m2_cipher = { + "Romulus-M2", + ROMULUS_KEY_SIZE, + ROMULUS2_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m2_aead_encrypt, + romulus_m2_aead_decrypt +}; + +aead_cipher_t const romulus_m3_cipher = { + "Romulus-M3", + ROMULUS_KEY_SIZE, + ROMULUS3_NONCE_SIZE, + ROMULUS_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + romulus_m3_aead_encrypt, + romulus_m3_aead_decrypt +}; + +/** + * \brief Limit on the number of bytes of message or associated data (128Mb). + * + * Romulus-N1 and Romulus-M1 use a 56-bit block counter which allows for + * payloads well into the petabyte range. It is unlikely that an embedded + * device will have that much memory to store a contiguous packet! + * + * Romulus-N2 and Romulus-M2 use a 48-bit block counter but the upper + * 24 bits are difficult to modify in the key schedule. So we only + * update the low 24 bits and leave the high 24 bits fixed. + * + * Romulus-N3 and Romulus-M3 use a 24-bit block counter. + * + * For all algorithms, we limit the block counter to 2^23 so that the block + * counter can never exceed 2^24 - 1. + */ +#define ROMULUS_DATA_LIMIT \ + ((unsigned long long)((1ULL << 23) * SKINNY_128_BLOCK_SIZE)) + +/** + * \brief Initializes the key schedule for Romulus-N1 or Romulus-M1. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 16 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus1_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + if (npub) + memcpy(TK, npub, 16); + else + memset(TK, 0, 16); + memcpy(TK + 16, k, 16); + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the 56-bit LFSR counter */ +} + +/** + * \brief Initializes the key schedule for Romulus-N2 or Romulus-M2. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus2_init + (skinny_128_384_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + unsigned char TK[32]; + memcpy(TK, k, 16); + memset(TK + 16, 0, 16); + TK[16] = 0x01; /* Initialize the high 24 bits of the LFSR counter */ + skinny_128_384_init(ks, TK, sizeof(TK)); + ks->TK1[0] = 0x01; /* Initialize the low 24 bits of the LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Initializes the key schedule for Romulus-N3 or Romulus-M3. + * + * \param ks Points to the key schedule to initialize. + * \param k Points to the 16 bytes of the key. + * \param npub Points to the 12 bytes of the nonce. May be NULL + * if the nonce will be updated on the fly. + */ +static void romulus3_init + (skinny_128_256_key_schedule_t *ks, + const unsigned char *k, const unsigned char *npub) +{ + skinny_128_256_init(ks, k, 16); + ks->TK1[0] = 0x01; /* Initialize the 24-bit LFSR counter */ + if (npub) + memcpy(ks->TK1 + 4, npub, 12); +} + +/** + * \brief Sets the domain separation value for Romulus-N1 and M1. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus1_set_domain(ks, domain) ((ks)->TK1[7] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N2 and M2. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus2_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Sets the domain separation value for Romulus-N3 and M3. + * + * \param ks The key schedule to set the domain separation value into. + * \param domain The domain separation value. + */ +#define romulus3_set_domain(ks, domain) ((ks)->TK1[3] = (domain)) + +/** + * \brief Updates the 56-bit LFSR block counter for Romulus-N1 and M1. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +STATIC_INLINE void romulus1_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[6])) >> 7); + TK1[6] = (TK1[6] << 1) | (TK1[5] >> 7); + TK1[5] = (TK1[5] << 1) | (TK1[4] >> 7); + TK1[4] = (TK1[4] << 1) | (TK1[3] >> 7); + TK1[3] = (TK1[3] << 1) | (TK1[2] >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x95); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N2 or M2. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + * + * For Romulus-N2 and Romulus-M2 this will only update the low 24 bits of + * the 48-bit LFSR. The high 24 bits are fixed due to ROMULUS_DATA_LIMIT. + */ +STATIC_INLINE void romulus2_update_counter(uint8_t TK1[16]) +{ + uint8_t mask = (uint8_t)(((int8_t)(TK1[2])) >> 7); + TK1[2] = (TK1[2] << 1) | (TK1[1] >> 7); + TK1[1] = (TK1[1] << 1) | (TK1[0] >> 7); + TK1[0] = (TK1[0] << 1) ^ (mask & 0x1B); +} + +/** + * \brief Updates the 24-bit LFSR block counter for Romulus-N3 or M3. + * + * \param TK1 Points to the TK1 part of the key schedule containing the LFSR. + */ +#define romulus3_update_counter(TK1) romulus2_update_counter((TK1)) + +/** + * \brief Process the asssociated data for Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + skinny_128_384_encrypt_tk2(ks, S, S, npub); + return; + } + + /* Process all double blocks except the last */ + romulus1_set_domain(ks, 0x08); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Pad and process the left-over blocks */ + romulus1_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 32) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x18); + } else if (temp > 16) { + /* Left-over partial double block */ + unsigned char pad[16]; + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, 15 - temp); + pad[15] = temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x1A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus1_set_domain(ks, 0x18); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus1_set_domain(ks, 0x1A); + } + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus2_set_domain(ks, 0x48); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus2_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x58); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x5A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus2_set_domain(ks, 0x58); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus2_set_domain(ks, 0x5A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void romulus_n3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char temp; + + /* Handle the special case of no associated data */ + if (adlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all double blocks except the last */ + romulus3_set_domain(ks, 0x88); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Pad and process the left-over blocks */ + romulus3_update_counter(ks->TK1); + temp = (unsigned)adlen; + if (temp == 28) { + /* Left-over complete double block */ + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x98); + } else if (temp > 16) { + /* Left-over partial double block */ + temp -= 16; + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp); + ks->TK1[15] = temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x9A); + } else if (temp == 16) { + /* Left-over complete single block */ + lw_xor_block(S, ad, temp); + romulus3_set_domain(ks, 0x98); + } else { + /* Left-over partial single block */ + lw_xor_block(S, ad, temp); + S[15] ^= temp; + romulus3_set_domain(ks, 0x9A); + } + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Determine the domain separation value to use on the last + * block of the associated data processing. + * + * \param adlen Length of the associated data in bytes. + * \param mlen Length of the message in bytes. + * \param t Size of the second half of a double block; 12 or 16. + * + * \return The domain separation bits to use to finalize the last block. + */ +static uint8_t romulus_m_final_ad_domain + (unsigned long long adlen, unsigned long long mlen, unsigned t) +{ + uint8_t domain = 0; + unsigned split = 16U; + unsigned leftover; + + /* Determine which domain bits we need based on the length of the ad */ + if (adlen == 0) { + /* No associated data, so only 1 block with padding */ + domain ^= 0x02; + split = t; + } else { + /* Even or odd associated data length? */ + leftover = (unsigned)(adlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x08; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x02; + split = t; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x0A; + } else { + /* Odd with a full single block at the end */ + split = t; + } + } + + /* Determine which domain bits we need based on the length of the message */ + if (mlen == 0) { + /* No message, so only 1 block with padding */ + domain ^= 0x01; + } else { + /* Even or odd message length? */ + leftover = (unsigned)(mlen % (16U + t)); + if (leftover == 0) { + /* Even with a full double block at the end */ + domain ^= 0x04; + } else if (leftover < split) { + /* Odd with a partial single block at the end */ + domain ^= 0x01; + } else if (leftover > split) { + /* Even with a partial double block at the end */ + domain ^= 0x05; + } + } + return domain; +} + +/** + * \brief Process the asssociated data for Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m1_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char pad[16]; + uint8_t final_domain = 0x30; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 16); + + /* Process all associated data double blocks except the last */ + romulus1_set_domain(ks, 0x28); + while (adlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + ad += 32; + adlen -= 32; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 32) { + /* Last associated data double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + skinny_128_384_encrypt_tk2(ks, S, S, ad + 16); + romulus1_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(pad, ad + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + romulus1_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus1_set_domain(ks, 0x2C); + romulus1_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + romulus1_update_counter(ks->TK1); + m += 16; + mlen -= 16; + } else if (mlen == 16) { + skinny_128_384_encrypt_tk2(ks, S, S, m); + m += 16; + mlen -= 16; + } else { + temp = (unsigned)mlen; + memcpy(pad, m, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus1_set_domain(ks, 0x2C); + while (mlen > 32) { + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + romulus1_update_counter(ks->TK1); + m += 32; + mlen -= 32; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 32) { + /* Last message double block is full */ + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + skinny_128_384_encrypt_tk2(ks, S, S, m + 16); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus1_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(pad, m + 16, temp); + memset(pad + temp, 0, sizeof(pad) - temp - 1); + pad[sizeof(pad) - 1] = (unsigned char)temp; + skinny_128_384_encrypt_tk2(ks, S, S, pad); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus1_set_domain(ks, final_domain); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt_tk2(ks, S, S, npub); +} + +/** + * \brief Process the asssociated data for Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m2_process_ad + (skinny_128_384_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0x70; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus2_set_domain(ks, 0x68); + while (adlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus2_set_domain(ks, 0x6C); + romulus2_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_384_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus2_set_domain(ks, 0x6C); + while (mlen > 28) { + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + romulus2_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_384_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus2_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_384_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus2_set_domain(ks, final_domain); + romulus2_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Process the asssociated data for Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param npub Points to the nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + * \param m Points to the message plaintext. + * \param mlen Length of the message plaintext. + */ +static void romulus_m3_process_ad + (skinny_128_256_key_schedule_t *ks, + unsigned char S[16], const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *m, unsigned long long mlen) +{ + uint8_t final_domain = 0xB0; + unsigned temp; + + /* Determine the domain separator to use on the final block */ + final_domain ^= romulus_m_final_ad_domain(adlen, mlen, 12); + + /* Process all associated data double blocks except the last */ + romulus3_set_domain(ks, 0xA8); + while (adlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + ad += 28; + adlen -= 28; + } + + /* Process the last associated data double block */ + temp = (unsigned)adlen; + if (temp == 28) { + /* Last associated data double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else if (temp > 16) { + /* Last associated data double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, ad, 16); + memcpy(ks->TK1 + 4, ad + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + } else { + /* Last associated data block is single. Needs to be combined + * with the first block of the message payload */ + romulus3_set_domain(ks, 0xAC); + romulus3_update_counter(ks->TK1); + if (temp == 16) { + lw_xor_block(S, ad, 16); + } else { + lw_xor_block(S, ad, temp); + S[15] ^= (unsigned char)temp; + } + if (mlen > 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 12; + mlen -= 12; + } else if (mlen == 12) { + memcpy(ks->TK1 + 4, m, 12); + skinny_128_256_encrypt(ks, S, S); + m += 12; + mlen -= 12; + } else { + temp = (unsigned)mlen; + memcpy(ks->TK1 + 4, m, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + mlen = 0; + } + } + + /* Process all message double blocks except the last */ + romulus3_set_domain(ks, 0xAC); + while (mlen > 28) { + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + romulus3_update_counter(ks->TK1); + m += 28; + mlen -= 28; + } + + /* Process the last message double block */ + temp = (unsigned)mlen; + if (temp == 28) { + /* Last message double block is full */ + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, 12); + skinny_128_256_encrypt(ks, S, S); + } else if (temp > 16) { + /* Last message double block is partial */ + temp -= 16; + romulus3_update_counter(ks->TK1); + lw_xor_block(S, m, 16); + memcpy(ks->TK1 + 4, m + 16, temp); + memset(ks->TK1 + 4 + temp, 0, 12 - temp - 1); + ks->TK1[15] = (unsigned char)temp; + skinny_128_256_encrypt(ks, S, S); + } else if (temp == 16) { + /* Last message single block is full */ + lw_xor_block(S, m, 16); + } else if (temp > 0) { + /* Last message single block is partial */ + lw_xor_block(S, m, temp); + S[15] ^= (unsigned char)temp; + } + + /* Process the last partial block */ + romulus3_set_domain(ks, final_domain); + romulus3_update_counter(ks->TK1); + memcpy(ks->TK1 + 4, npub, 12); + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Applies the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + */ +STATIC_INLINE void romulus_rho + (unsigned char S[16], unsigned char C[16], const unsigned char M[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } +} + +/** + * \brief Applies the inverse of the Romulus rho function. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + */ +STATIC_INLINE void romulus_rho_inverse + (unsigned char S[16], unsigned char M[16], const unsigned char C[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } +} + +/** + * \brief Applies the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param C Ciphertext message output block. + * \param M Plaintext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_short + (unsigned char S[16], unsigned char C[16], + const unsigned char M[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = M[index]; + S[index] ^= m; + C[index] = m ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Applies the inverse of the Romulus rho function to a short block. + * + * \param S The rolling Romulus state. + * \param M Plaintext message output block. + * \param C Ciphertext message input block. + * \param len Length of the short block, must be less than 16. + */ +STATIC_INLINE void romulus_rho_inverse_short + (unsigned char S[16], unsigned char M[16], + const unsigned char C[16], unsigned len) +{ + unsigned index; + for (index = 0; index < len; ++index) { + unsigned char s = S[index]; + unsigned char m = C[index] ^ ((s >> 1) ^ (s & 0x80) ^ (s << 7)); + S[index] ^= m; + M[index] = m; + } + S[15] ^= (unsigned char)len; /* Padding */ +} + +/** + * \brief Encrypts a plaintext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho(S, c, m); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus1_update_counter(ks->TK1); + romulus1_set_domain(ks, 0x15); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus1_set_domain(ks, 0x04); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus1_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus1_set_domain(ks, 0x15); + } else { + romulus_rho_inverse(S, m, c); + romulus1_set_domain(ks, 0x14); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho(S, c, m); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus2_update_counter(ks->TK1); + romulus2_set_domain(ks, 0x55); + skinny_128_384_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus2_set_domain(ks, 0x44); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + skinny_128_384_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus2_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus2_set_domain(ks, 0x55); + } else { + romulus_rho_inverse(S, m, c); + romulus2_set_domain(ks, 0x54); + } + skinny_128_384_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no plaintext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_short(S, c, m, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho(S, c, m); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-N3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_n3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + unsigned temp; + + /* Handle the special case of no ciphertext */ + if (mlen == 0) { + romulus3_update_counter(ks->TK1); + romulus3_set_domain(ks, 0x95); + skinny_128_256_encrypt(ks, S, S); + return; + } + + /* Process all blocks except the last */ + romulus3_set_domain(ks, 0x84); + while (mlen > 16) { + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + skinny_128_256_encrypt(ks, S, S); + c += 16; + m += 16; + mlen -= 16; + } + + /* Pad and process the last block */ + temp = (unsigned)mlen; + romulus3_update_counter(ks->TK1); + if (temp < 16) { + romulus_rho_inverse_short(S, m, c, temp); + romulus3_set_domain(ks, 0x95); + } else { + romulus_rho_inverse(S, m, c); + romulus3_set_domain(ks, 0x94); + } + skinny_128_256_encrypt(ks, S, S); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M1. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m1_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus1_set_domain(ks, 0x24); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus1_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M2. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m2_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus2_set_domain(ks, 0x64); + while (mlen > 16) { + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus2_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_384_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Encrypts a plaintext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the buffer containing the plaintext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *c, const unsigned char *m, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho(S, c, m); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_short(S, c, m, (unsigned)mlen); +} + +/** + * \brief Decrypts a ciphertext message with Romulus-M3. + * + * \param ks Points to the key schedule. + * \param S The rolling Romulus state. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the buffer containing the ciphertext. + * \param mlen Length of the plaintext in bytes. + */ +static void romulus_m3_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char S[16], + unsigned char *m, const unsigned char *c, unsigned long long mlen) +{ + /* Nothing to do if the message is empty */ + if (!mlen) + return; + + /* Process all block except the last */ + romulus3_set_domain(ks, 0xA4); + while (mlen > 16) { + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse(S, m, c); + romulus3_update_counter(ks->TK1); + c += 16; + m += 16; + mlen -= 16; + } + + /* Handle the last block */ + skinny_128_256_encrypt(ks, S, S); + romulus_rho_inverse_short(S, m, c, (unsigned)mlen); +} + +/** + * \brief Generates the authentication tag from the rolling Romulus state. + * + * \param T Buffer to receive the generated tag; can be the same as S. + * \param S The rolling Romulus state. + */ +STATIC_INLINE void romulus_generate_tag + (unsigned char T[16], const unsigned char S[16]) +{ + unsigned index; + for (index = 0; index < 16; ++index) { + unsigned char s = S[index]; + T[index] = (s >> 1) ^ (s & 0x80) ^ (s << 7); + } +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n1_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n1_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n1_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n2_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n2_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n2_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypts the plaintext to produce the ciphertext */ + romulus_n3_encrypt(&ks, S, c, m, mlen); + + /* Generate the authentication tag */ + romulus_generate_tag(c + mlen, S); + return 0; +} + +int romulus_n3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_n3_process_ad(&ks, S, npub, ad, adlen); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= ROMULUS_TAG_SIZE; + romulus_n3_decrypt(&ks, S, m, c, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m1_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus1_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m1_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus1_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m1_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m2_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus2_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m2_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus2_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m2_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || mlen > ROMULUS_DATA_LIMIT) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data and the plaintext message */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, mlen); + + /* Generate the authentication tag, which is also the initialization + * vector for the encryption portion of the packet processing */ + romulus_generate_tag(S, S); + memcpy(c + mlen, S, ROMULUS_TAG_SIZE); + + /* Re-initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Encrypt the plaintext to produce the ciphertext */ + romulus_m3_encrypt(&ks, S, c, m, mlen); + return 0; +} + +int romulus_m3_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char S[16]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < ROMULUS_TAG_SIZE) + return -1; + *mlen = clen - ROMULUS_TAG_SIZE; + + /* Validate the length of the associated data and message */ + if (adlen > ROMULUS_DATA_LIMIT || + clen > (ROMULUS_DATA_LIMIT + ROMULUS_TAG_SIZE)) + return -2; + + /* Initialize the key schedule with the key and nonce */ + romulus3_init(&ks, k, npub); + + /* Decrypt the ciphertext to produce the plaintext, using the + * authentication tag as the initialization vector for decryption */ + clen -= ROMULUS_TAG_SIZE; + memcpy(S, c + clen, ROMULUS_TAG_SIZE); + romulus_m3_decrypt(&ks, S, m, c, clen); + + /* Re-initialize the key schedule with the key and no nonce. Associated + * data processing varies the nonce from block to block */ + romulus3_init(&ks, k, 0); + + /* Process the associated data */ + memset(S, 0, sizeof(S)); + romulus_m3_process_ad(&ks, S, npub, ad, adlen, m, clen); + + /* Check the authentication tag */ + romulus_generate_tag(S, S); + return aead_check_tag(m, clen, S, c + clen, ROMULUS_TAG_SIZE); +} diff --git a/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.h b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.h new file mode 100644 index 0000000..e6da29d --- /dev/null +++ b/romulus/Implementations/crypto_aead/romulusn3v12/rhys/romulus.h @@ -0,0 +1,476 @@ +/* + * 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_ROMULUS_H +#define LWCRYPTO_ROMULUS_H + +#include "aead-common.h" + +/** + * \file romulus.h + * \brief Romulus authenticated encryption algorithm family. + * + * Romulus is a family of authenticated encryption algorithms that + * are built around the SKINNY-128 tweakable block cipher. There + * are six members in the family: + * + * \li Romulus-N1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li Romulus-N2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-N3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li Romulus-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li Romulus-M3 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The Romulus-M variants are resistant to nonce reuse as long as the + * combination of the associated data and plaintext is unique. If the + * same associated data and plaintext are reused under the same nonce, + * then the scheme will leak that the same plaintext has been sent for a + * second time but will not reveal the plaintext itself. + * + * References: https://romulusae.github.io/romulus/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all Romulus family members. + */ +#define ROMULUS_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all Romulus family members. + */ +#define ROMULUS_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N1 and Romulus-M1. + */ +#define ROMULUS1_NONCE_SIZE 16 + +/** + * \brief Size of the nonce for Romulus-N2 and Romulus-M2. + */ +#define ROMULUS2_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for Romulus-N3 and Romulus-M3. + */ +#define ROMULUS3_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the Romulus-N1 cipher. + */ +extern aead_cipher_t const romulus_n1_cipher; + +/** + * \brief Meta-information block for the Romulus-N2 cipher. + */ +extern aead_cipher_t const romulus_n2_cipher; + +/** + * \brief Meta-information block for the Romulus-N3 cipher. + */ +extern aead_cipher_t const romulus_n3_cipher; + +/** + * \brief Meta-information block for the Romulus-M1 cipher. + */ +extern aead_cipher_t const romulus_m1_cipher; + +/** + * \brief Meta-information block for the Romulus-M2 cipher. + */ +extern aead_cipher_t const romulus_m2_cipher; + +/** + * \brief Meta-information block for the Romulus-M3 cipher. + */ +extern aead_cipher_t const romulus_m3_cipher; + +/** + * \brief Encrypts and authenticates a packet with Romulus-N1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n1_aead_decrypt() + */ +int romulus_n1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n1_aead_encrypt() + */ +int romulus_n1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n2_aead_decrypt() + */ +int romulus_n2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n2_aead_encrypt() + */ +int romulus_n2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-N3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_n3_aead_decrypt() + */ +int romulus_n3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-N3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_n3_aead_encrypt() + */ +int romulus_n3_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m1_aead_decrypt() + */ +int romulus_m1_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m1_aead_encrypt() + */ +int romulus_m1_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m2_aead_decrypt() + */ +int romulus_m2_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m2_aead_encrypt() + */ +int romulus_m2_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); + +/** + * \brief Encrypts and authenticates a packet with Romulus-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa romulus_m3_aead_decrypt() + */ +int romulus_m3_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); + +/** + * \brief Decrypts and authenticates a packet with Romulus-M3. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa romulus_m3_aead_encrypt() + */ +int romulus_m3_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.c b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.h b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/api.h b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/api.h new file mode 100644 index 0000000..75fabd7 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 32 +#define CRYPTO_NOOVERLAP 1 diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/encrypt.c b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/encrypt.c new file mode 100644 index 0000000..9ce5559 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "saturnin.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 saturnin_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 saturnin_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/internal-util.h b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.c b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.c new file mode 100644 index 0000000..734fc69 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.c @@ -0,0 +1,781 @@ +/* + * 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 "saturnin.h" +#include "internal-util.h" +#include + +aead_cipher_t const saturnin_cipher = { + "SATURNIN-CTR-Cascade", + SATURNIN_KEY_SIZE, + SATURNIN_NONCE_SIZE, + SATURNIN_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + saturnin_aead_encrypt, + saturnin_aead_decrypt +}; + +aead_cipher_t const saturnin_short_cipher = { + "SATURNIN-Short", + SATURNIN_KEY_SIZE, + SATURNIN_NONCE_SIZE, + SATURNIN_TAG_SIZE, + AEAD_FLAG_NONE, + saturnin_short_aead_encrypt, + saturnin_short_aead_decrypt +}; + +aead_hash_algorithm_t const saturnin_hash_algorithm = { + "SATURNIN-Hash", + sizeof(saturnin_hash_state_t), + SATURNIN_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + saturnin_hash, + (aead_hash_init_t)saturnin_hash_init, + (aead_hash_update_t)saturnin_hash_update, + (aead_hash_finalize_t)saturnin_hash_finalize, + 0, /* absorb */ + 0 /* squeeze */ +}; + +/* Round constant tables for various combinations of rounds and domain_sep */ +static uint32_t const RC_10_1[] = { + 0x4eb026c2, 0x90595303, 0xaa8fe632, 0xfe928a92, 0x4115a419, + 0x93539532, 0x5db1cc4e, 0x541515ca, 0xbd1f55a8, 0x5a6e1a0d +}; +static uint32_t const RC_10_2[] = { + 0x4e4526b5, 0xa3565ff0, 0x0f8f20d8, 0x0b54bee1, 0x7d1a6c9d, + 0x17a6280a, 0xaa46c986, 0xc1199062, 0x182c5cde, 0xa00d53fe +}; +static uint32_t const RC_10_3[] = { + 0x4e162698, 0xb2535ba1, 0x6c8f9d65, 0x5816ad30, 0x691fd4fa, + 0x6bf5bcf9, 0xf8eb3525, 0xb21decfa, 0x7b3da417, 0xf62c94b4 +}; +static uint32_t const RC_10_4[] = { + 0x4faf265b, 0xc5484616, 0x45dcad21, 0xe08bd607, 0x0504fdb8, + 0x1e1f5257, 0x45fbc216, 0xeb529b1f, 0x52194e32, 0x5498c018 +}; +static uint32_t const RC_10_5[] = { + 0x4ffc2676, 0xd44d4247, 0x26dc109c, 0xb3c9c5d6, 0x110145df, + 0x624cc6a4, 0x17563eb5, 0x9856e787, 0x3108b6fb, 0x02b90752 +}; +static uint32_t const RC_10_6[] = { + 0x4f092601, 0xe7424eb4, 0x83dcd676, 0x460ff1a5, 0x2d0e8d5b, + 0xe6b97b9c, 0xe0a13b7d, 0x0d5a622f, 0x943bbf8d, 0xf8da4ea1 +}; +static uint32_t const RC_16_7[] = { + 0x3fba180c, 0x563ab9ab, 0x125ea5ef, 0x859da26c, 0xb8cf779b, + 0x7d4de793, 0x07efb49f, 0x8d525306, 0x1e08e6ab, 0x41729f87, + 0x8c4aef0a, 0x4aa0c9a7, 0xd93a95ef, 0xbb00d2af, 0xb62c5bf0, + 0x386d94d8 +}; +static uint32_t const RC_16_8[] = { + 0x3c9b19a7, 0xa9098694, 0x23f878da, 0xa7b647d3, 0x74fc9d78, + 0xeacaae11, 0x2f31a677, 0x4cc8c054, 0x2f51ca05, 0x5268f195, + 0x4f5b8a2b, 0xf614b4ac, 0xf1d95401, 0x764d2568, 0x6a493611, + 0x8eef9c3e +}; + +/* Rotate the 4-bit nibbles within a 16-bit word left */ +#define leftRotate4_N(a, mask1, bits1, mask2, bits2) \ + do { \ + uint32_t _temp = (a); \ + (a) = ((_temp & (mask1)) << (bits1)) | \ + ((_temp & ((mask1) ^ (uint32_t)0xFFFFU)) >> (4 - (bits1))) | \ + ((_temp & (((uint32_t)(mask2)) << 16)) << (bits2)) | \ + ((_temp & (((uint32_t)((mask2)) << 16) ^ 0xFFFF0000U)) >> (4 - (bits2))); \ + } while (0) + +/* Rotate 16-bit subwords left */ +#define leftRotate16_N(a, mask1, bits1, mask2, bits2) \ + do { \ + uint32_t _temp = (a); \ + (a) = ((_temp & (mask1)) << (bits1)) | \ + ((_temp & ((mask1) ^ (uint32_t)0xFFFFU)) >> (16 - (bits1))) | \ + ((_temp & (((uint32_t)(mask2)) << 16)) << (bits2)) | \ + ((_temp & (((uint32_t)((mask2)) << 16) ^ 0xFFFF0000U)) >> (16 - (bits2))); \ + } while (0) + +/* XOR the SATURNIN state with the key */ +#define saturnin_xor_key() \ + do { \ + for (index = 0; index < 8; ++index) \ + S[index] ^= K[index]; \ + } while (0) + +/* XOR the SATURNIN state with a rotated version of the key */ +#define saturnin_xor_key_rotated() \ + do { \ + for (index = 0; index < 8; ++index) \ + S[index] ^= K[index + 8]; \ + } while (0) + +/* Apply an SBOX layer for SATURNIN - definition from the specification */ +#define S_LAYER(a, b, c, d) \ + do { \ + (a) ^= (b) & (c); \ + (b) ^= (a) | (d); \ + (d) ^= (b) | (c); \ + (c) ^= (b) & (d); \ + (b) ^= (a) | (c); \ + (a) ^= (b) | (d); \ + } while (0) + +/* Apply an SBOX layer for SATURNIN in reverse */ +#define S_LAYER_INVERSE(a, b, c, d) \ + do { \ + (a) ^= (b) | (d); \ + (b) ^= (a) | (c); \ + (c) ^= (b) & (d); \ + (d) ^= (b) | (c); \ + (b) ^= (a) | (d); \ + (a) ^= (b) & (c); \ + } while (0) + +/** + * \brief Applies the SBOX to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sbox(uint32_t S[8]) +{ + uint32_t a, b, c, d; + + /* PI_0 on the first half of the state */ + a = S[0]; b = S[1]; c = S[2]; d = S[3]; + S_LAYER(a, b, c, d); + S[0] = b; S[1] = c; S[2] = d; S[3] = a; + + /* PI_1 on the second half of the state */ + a = S[4]; b = S[5]; c = S[6]; d = S[7]; + S_LAYER(a, b, c, d); + S[4] = d; S[5] = b; S[6] = a; S[7] = c; +} + +/** + * \brief Applies the inverse of the SBOX to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sbox_inverse(uint32_t S[8]) +{ + uint32_t a, b, c, d; + + /* PI_0 on the first half of the state */ + b = S[0]; c = S[1]; d = S[2]; a = S[3]; + S_LAYER_INVERSE(a, b, c, d); + S[0] = a; S[1] = b; S[2] = c; S[3] = d; + + /* PI_1 on the second half of the state */ + d = S[4]; b = S[5]; a = S[6]; c = S[7]; + S_LAYER_INVERSE(a, b, c, d); + S[4] = a; S[5] = b; S[6] = c; S[7] = d; +} + +/** + * \brief Applies the MDS matrix to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_mds(uint32_t S[8]) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t tmp; + + /* Load the state into temporary working variables */ + x0 = S[0]; x1 = S[1]; x2 = S[2]; x3 = S[3]; + x4 = S[4]; x5 = S[5]; x6 = S[6]; x7 = S[7]; + + /* Apply the MDS matrix to the state */ + #define SWAP(a) (((a) << 16) | ((a) >> 16)) + #define MUL(x0, x1, x2, x3, tmp) \ + do { \ + tmp = x0; x0 = x1; x1 = x2; x2 = x3; x3 = tmp ^ x0; \ + } while (0) + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + MUL(x4, x5, x6, x7, tmp); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + MUL(x0, x1, x2, x3, tmp); + MUL(x0, x1, x2, x3, tmp); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + + /* Store the temporary working variables back into the state */ + S[0] = x0; S[1] = x1; S[2] = x2; S[3] = x3; + S[4] = x4; S[5] = x5; S[6] = x6; S[7] = x7; +} + +/** + * \brief Applies the inverse of the MDS matrix to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_mds_inverse(uint32_t S[8]) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t tmp; + + /* Load the state into temporary working variables */ + x0 = S[0]; x1 = S[1]; x2 = S[2]; x3 = S[3]; + x4 = S[4]; x5 = S[5]; x6 = S[6]; x7 = S[7]; + + /* Apply the inverse of the MDS matrix to the state */ + #define MULINV(x0, x1, x2, x3, tmp) \ + do { \ + tmp = x3; x3 = x2; x2 = x1; x1 = x0; x0 = x1 ^ tmp; \ + } while (0) + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + MULINV(x0, x1, x2, x3, tmp); + MULINV(x0, x1, x2, x3, tmp); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + MULINV(x4, x5, x6, x7, tmp); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + + /* Store the temporary working variables back into the state */ + S[0] = x0; S[1] = x1; S[2] = x2; S[3] = x3; + S[4] = x4; S[5] = x5; S[6] = x6; S[7] = x7; +} + +/** + * \brief Applies the slice permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_slice(uint32_t S[8]) +{ + leftRotate4_N(S[0], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[1], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[2], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[3], 0xFFFFU, 0, 0x3333, 2); + + leftRotate4_N(S[4], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[5], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[6], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[7], 0x7777U, 1, 0x1111, 3); +} + +/** + * \brief Applies the inverse of the slice permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_slice_inverse(uint32_t S[8]) +{ + leftRotate4_N(S[0], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[1], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[2], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[3], 0xFFFFU, 0, 0x3333, 2); + + leftRotate4_N(S[4], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[5], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[6], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[7], 0x1111U, 3, 0x7777, 1); +} + +/** + * \brief Applies the sheet permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sheet(uint32_t S[8]) +{ + leftRotate16_N(S[0], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[1], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[2], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[3], 0xFFFFU, 0, 0x00FF, 8); + + leftRotate16_N(S[4], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[5], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[6], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[7], 0x0FFFU, 4, 0x000F, 12); +} + +/** + * \brief Applies the inverse of the sheet permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sheet_inverse(uint32_t S[8]) +{ + leftRotate16_N(S[0], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[1], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[2], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[3], 0xFFFFU, 0, 0x00FF, 8); + + leftRotate16_N(S[4], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[5], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[6], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[7], 0x000FU, 12, 0x0FFF, 4); +} + +/** + * \brief Encrypts a 256-bit block with the SATURNIN block cipher. + * + * \param output Ciphertext output block, 32 bytes. + * \param input Plaintext input block, 32 bytes. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + * + * The \a input and \a output buffers can be the same. + * + * \sa saturnin_block_decrypt() + */ +static void saturnin_block_encrypt + (unsigned char *output, const unsigned char *input, + const unsigned char *key, unsigned rounds, const uint32_t *RC) +{ + uint32_t K[16]; + uint32_t S[8]; + uint32_t temp; + unsigned index; + + /* Unpack the key and the input block */ + for (index = 0; index < 16; index += 2) { + temp = ((uint32_t)(key[index])) | + (((uint32_t)(key[index + 1])) << 8) | + (((uint32_t)(key[index + 16])) << 16) | + (((uint32_t)(key[index + 17])) << 24); + K[index / 2] = temp; + K[8 + (index / 2)] = ((temp & 0x001F001FU) << 11) | + ((temp >> 5) & 0x07FF07FFU); + S[index / 2] = ((uint32_t)(input[index])) | + (((uint32_t)(input[index + 1])) << 8) | + (((uint32_t)(input[index + 16])) << 16) | + (((uint32_t)(input[index + 17])) << 24); + } + + /* XOR the key into the state */ + saturnin_xor_key(); + + /* Perform all encryption rounds */ + for (; rounds > 0; rounds -= 2, RC += 2) { + saturnin_sbox(S); + saturnin_mds(S); + saturnin_sbox(S); + saturnin_slice(S); + saturnin_mds(S); + saturnin_slice_inverse(S); + S[0] ^= RC[0]; + saturnin_xor_key_rotated(); + + saturnin_sbox(S); + saturnin_mds(S); + saturnin_sbox(S); + saturnin_sheet(S); + saturnin_mds(S); + saturnin_sheet_inverse(S); + S[0] ^= RC[1]; + saturnin_xor_key(); + } + + /* Encode the state into the output block */ + for (index = 0; index < 16; index += 2) { + temp = S[index / 2]; + output[index] = (uint8_t)temp; + output[index + 1] = (uint8_t)(temp >> 8); + output[index + 16] = (uint8_t)(temp >> 16); + output[index + 17] = (uint8_t)(temp >> 24); + } +} + +/** + * \brief Decrypts a 256-bit block with the SATURNIN block cipher. + * + * \param output Plaintext output block, 32 bytes. + * \param input Ciphertext input block, 32 bytes. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + * + * The \a input and \a output buffers can be the same. + * + * \sa saturnin_block_encrypt() + */ +static void saturnin_block_decrypt + (unsigned char *output, const unsigned char *input, + const unsigned char *key, unsigned rounds, const uint32_t *RC) +{ + uint32_t K[16]; + uint32_t S[8]; + uint32_t temp; + unsigned index; + + /* Unpack the key and the input block */ + for (index = 0; index < 16; index += 2) { + temp = ((uint32_t)(key[index])) | + (((uint32_t)(key[index + 1])) << 8) | + (((uint32_t)(key[index + 16])) << 16) | + (((uint32_t)(key[index + 17])) << 24); + K[index / 2] = temp; + K[8 + (index / 2)] = ((temp & 0x001F001FU) << 11) | + ((temp >> 5) & 0x07FF07FFU); + S[index / 2] = ((uint32_t)(input[index])) | + (((uint32_t)(input[index + 1])) << 8) | + (((uint32_t)(input[index + 16])) << 16) | + (((uint32_t)(input[index + 17])) << 24); + } + + /* Perform all decryption rounds */ + RC += rounds - 2; + for (; rounds > 0; rounds -= 2, RC -= 2) { + saturnin_xor_key(); + S[0] ^= RC[1]; + saturnin_sheet(S); + saturnin_mds_inverse(S); + saturnin_sheet_inverse(S); + saturnin_sbox_inverse(S); + saturnin_mds_inverse(S); + saturnin_sbox_inverse(S); + + saturnin_xor_key_rotated(); + S[0] ^= RC[0]; + saturnin_slice(S); + saturnin_mds_inverse(S); + saturnin_slice_inverse(S); + saturnin_sbox_inverse(S); + saturnin_mds_inverse(S); + saturnin_sbox_inverse(S); + } + + /* XOR the key into the state */ + saturnin_xor_key(); + + /* Encode the state into the output block */ + for (index = 0; index < 16; index += 2) { + temp = S[index / 2]; + output[index] = (uint8_t)temp; + output[index + 1] = (uint8_t)(temp >> 8); + output[index + 16] = (uint8_t)(temp >> 16); + output[index + 17] = (uint8_t)(temp >> 24); + } +} + +/** + * \brief Encrypts a 256-bit block with the SATURNIN block cipher and + * then XOR's itself to generate a new key. + * + * \param block Block to be encrypted and then XOR'ed with itself. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + */ +void saturnin_block_encrypt_xor + (const unsigned char *block, unsigned char *key, + unsigned rounds, const uint32_t *RC) +{ + unsigned char temp[32]; + saturnin_block_encrypt(temp, block, key, rounds, RC); + lw_xor_block_2_src(key, block, temp, 32); +} + +/** + * \brief Encrypts (or decrypts) a data packet in CTR mode. + * + * \param c Output ciphertext buffer. + * \param m Input plaintext buffer. + * \param mlen Length of the plaintext in bytes. + * \param k Points to the 32-byte key. + * \param block Points to the pre-formatted nonce block. + */ +static void saturnin_ctr_encrypt + (unsigned char *c, const unsigned char *m, unsigned long long mlen, + const unsigned char *k, unsigned char *block) +{ + /* Note: Specification requires a 95-bit counter but we only use 32-bit. + * This limits the maximum packet size to 128Gb. That should be OK */ + uint32_t counter = 1; + unsigned char out[32]; + while (mlen >= 32) { + be_store_word32(block + 28, counter); + saturnin_block_encrypt(out, block, k, 10, RC_10_1); + lw_xor_block_2_src(c, out, m, 32); + c += 32; + m += 32; + mlen -= 32; + ++counter; + } + if (mlen > 0) { + be_store_word32(block + 28, counter); + saturnin_block_encrypt(out, block, k, 10, RC_10_1); + lw_xor_block_2_src(c, out, m, (unsigned)mlen); + } +} + +/** + * \brief Pads an authenticates a message. + * + * \param tag Points to the authentication tag. + * \param block Temporary block of 32 bytes from the caller. + * \param m Points to the message to be authenticated. + * \param mlen Length of the message to be authenticated in bytes. + * \param rounds Number of rounds to perform. + * \param RC1 Round constants to use for domain separation on full blocks. + * \param RC2 Round constants to use for domain separation on the last block. + */ +static void saturnin_authenticate + (unsigned char *tag, unsigned char *block, + const unsigned char *m, unsigned long long mlen, + unsigned rounds, const uint32_t *RC1, const uint32_t *RC2) +{ + unsigned temp; + while (mlen >= 32) { + saturnin_block_encrypt_xor(m, tag, rounds, RC1); + m += 32; + mlen -= 32; + } + temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, 31 - temp); + saturnin_block_encrypt_xor(block, tag, rounds, RC2); +} + +int saturnin_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) +{ + unsigned char block[32]; + unsigned char *tag; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SATURNIN_TAG_SIZE; + + /* Format the input block from the padded nonce */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + + /* Encrypt the plaintext in counter mode to produce the ciphertext */ + saturnin_ctr_encrypt(c, m, mlen, k, block); + + /* Set the counter back to zero and then encrypt the nonce */ + tag = c + mlen; + memcpy(tag, k, 32); + memset(block + 17, 0, 15); + saturnin_block_encrypt_xor(block, tag, 10, RC_10_2); + + /* Authenticate the associated data and the ciphertext */ + saturnin_authenticate(tag, block, ad, adlen, 10, RC_10_2, RC_10_3); + saturnin_authenticate(tag, block, c, mlen, 10, RC_10_4, RC_10_5); + return 0; +} + +int saturnin_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) +{ + unsigned char block[32]; + unsigned char tag[32]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SATURNIN_TAG_SIZE) + return -1; + *mlen = clen - SATURNIN_TAG_SIZE; + + /* Format the input block from the padded nonce */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + + /* Encrypt the nonce to initialize the authentication phase */ + memcpy(tag, k, 32); + saturnin_block_encrypt_xor(block, tag, 10, RC_10_2); + + /* Authenticate the associated data and the ciphertext */ + saturnin_authenticate(tag, block, ad, adlen, 10, RC_10_2, RC_10_3); + saturnin_authenticate(tag, block, c, *mlen, 10, RC_10_4, RC_10_5); + + /* Decrypt the ciphertext in counter mode to produce the plaintext */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + saturnin_ctr_encrypt(m, c, *mlen, k, block); + + /* Check the authentication tag at the end of the message */ + return aead_check_tag + (m, *mlen, tag, c + *mlen, SATURNIN_TAG_SIZE); +} + +int saturnin_short_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) +{ + unsigned char block[32]; + unsigned temp; + (void)nsec; + (void)ad; + + /* Validate the parameters: no associated data allowed and m <= 15 bytes */ + if (adlen > 0 || mlen > 15) + return -2; + + /* Format the input block from the nonce and plaintext */ + temp = (unsigned)mlen; + memcpy(block, npub, 16); + memcpy(block + 16, m, temp); + block[16 + temp] = 0x80; /* Padding */ + memset(block + 17 + temp, 0, 15 - temp); + + /* Encrypt the input block to produce the output ciphertext */ + saturnin_block_encrypt(c, block, k, 10, RC_10_6); + *clen = 32; + return 0; +} + +int saturnin_short_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) +{ + unsigned char block[32]; + unsigned check1, check2, len; + int index, result; + (void)nsec; + (void)ad; + + /* Validate the parameters: no associated data and c is always 32 bytes */ + if (adlen > 0) + return -2; + if (clen != 32) + return -1; + + /* Decrypt the ciphertext block */ + saturnin_block_decrypt(block, c, k, 10, RC_10_6); + + /* Verify that the output block starts with the nonce and that it is + * padded correctly. We need to do this very carefully to avoid leaking + * any information that could be used in a padding oracle attack. Use the + * same algorithm as the reference implementation of SATURNIN-Short */ + check1 = 0; + for (index = 0; index < 16; ++index) + check1 |= npub[index] ^ block[index]; + check2 = 0xFF; + len = 0; + for (index = 15; index >= 0; --index) { + unsigned temp = block[16 + index]; + unsigned temp2 = check2 & -(1 - (((temp ^ 0x80) + 0xFF) >> 8)); + len |= temp2 & (unsigned)index; + check2 &= ~temp2; + check1 |= check2 & ((temp + 0xFF) >> 8); + } + check1 |= check2; + + /* At this point, check1 is zero if the nonce and plaintext are good, + * or non-zero if there was an error in the decrypted data */ + result = (((int)check1) - 1) >> 8; + + /* The "result" is -1 if the data is good or zero if the data is invalid. + * Copy either the plaintext or zeroes to the output buffer. We assume + * that the output buffer has space for up to 15 bytes. This may return + * some of the padding to the caller but as long as they restrict + * themselves to the first *mlen bytes then it shouldn't be a problem */ + for (index = 0; index < 15; ++index) + m[index] = block[16 + index] & result; + *mlen = len; + return ~result; +} + +int saturnin_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char tag[32]; + unsigned char block[32]; + memset(tag, 0, sizeof(tag)); + saturnin_authenticate(tag, block, in, inlen, 16, RC_16_7, RC_16_8); + memcpy(out, tag, 32); + return 0; +} + +void saturnin_hash_init(saturnin_hash_state_t *state) +{ + memset(state, 0, sizeof(saturnin_hash_state_t)); +} + +void saturnin_hash_update + (saturnin_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + unsigned temp; + + /* Handle the partial left-over block from last time */ + if (state->s.count) { + temp = 32 - state->s.count; + if (temp > inlen) { + temp = (unsigned)inlen; + memcpy(state->s.block + state->s.count, in, temp); + state->s.count += temp; + return; + } + memcpy(state->s.block + state->s.count, in, temp); + state->s.count = 0; + in += temp; + inlen -= temp; + saturnin_block_encrypt_xor(state->s.block, state->s.hash, 16, RC_16_7); + } + + /* Process full blocks that are aligned at state->s.count == 0 */ + while (inlen >= 32) { + saturnin_block_encrypt_xor(in, state->s.hash, 16, RC_16_7); + in += 32; + inlen -= 32; + } + + /* Process the left-over block at the end of the input */ + temp = (unsigned)inlen; + memcpy(state->s.block, in, temp); + state->s.count = temp; +} + +void saturnin_hash_finalize + (saturnin_hash_state_t *state, unsigned char *out) +{ + /* Pad the final block */ + state->s.block[state->s.count] = 0x80; + memset(state->s.block + state->s.count + 1, 0, 31 - state->s.count); + + /* Generate the final hash value */ + saturnin_block_encrypt_xor(state->s.block, state->s.hash, 16, RC_16_8); + memcpy(out, state->s.hash, 32); +} diff --git a/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.h b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.h new file mode 100644 index 0000000..873d950 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninctrcascadev2/rhys/saturnin.h @@ -0,0 +1,270 @@ +/* + * 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_SATURNIN_H +#define LWCRYPTO_SATURNIN_H + +#include "aead-common.h" + +/** + * \file saturnin.h + * \brief Saturnin authenticated encryption algorithm. + * + * The Saturnin family consists of two members: SATURNIN-CTR-Cascade and + * SATURNIN-Short. Both take a 256-bit key and a 128-bit nonce. + * Internally they use a 256-bit block cipher similar in construction to AES. + * + * SATURNIN-Short does not support associated data or plaintext packets + * with more than 15 bytes. This makes it very efficient on short packets + * with only a single block operation involved. + * + * This implementation of SATURNIN-Short will return an error if the + * caller supplies associated data or more than 15 bytes of plaintext. + * + * References: https://project.inria.fr/saturnin/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SATURNIN family members. + */ +#define SATURNIN_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for SATURNIN-CTR-Cascade or the + * total size of the ciphertext for SATURNIN-Short. + */ +#define SATURNIN_TAG_SIZE 32 + +/** + * \brief Size of the nonce for all SATURNIN family members. + */ +#define SATURNIN_NONCE_SIZE 16 + +/** + * \brief Size of the hash for SATURNIN-Hash. + */ +#define SATURNIN_HASH_SIZE 32 + +/** + * \brief State information for SATURNIN-Hash incremental modes. + */ +typedef union +{ + struct { + unsigned char hash[32]; /**< Current hash state */ + unsigned char block[32]; /**< Left-over block data from last update */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} saturnin_hash_state_t; + +/** + * \brief Meta-information block for the SATURNIN-CTR-Cascade cipher. + */ +extern aead_cipher_t const saturnin_cipher; + +/** + * \brief Meta-information block for the SATURNIN-Short cipher. + */ +extern aead_cipher_t const saturnin_short_cipher; + +/** + * \brief Meta-information block for SATURNIN-Hash. + */ +extern aead_hash_algorithm_t const saturnin_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with SATURNIN-CTR-Cascade. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 32 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa saturnin_aead_decrypt() + */ +int saturnin_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); + +/** + * \brief Decrypts and authenticates a packet with SATURNIN-CTR-Cascade. + * + * \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 - not used by this algorithm. + * \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 32 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa saturnin_aead_encrypt() + */ +int saturnin_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); + +/** + * \brief Encrypts and authenticates a packet with SATURNIN-Short. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which is always 32. + * \param m Buffer that contains the plaintext message to encrypt. + * \param mlen Length of the plaintext message in bytes, which must be + * less than or equal to 15 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, which must be zero. + * \param nsec Secret nonce - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or -2 if the caller supplied too many bytes of + * plaintext or they supplied associated data. + * + * \sa saturnin_short_aead_decrypt() + */ +int saturnin_short_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); + +/** + * \brief Decrypts and authenticates a packet with SATURNIN-Short. + * + * \param m Buffer to receive the plaintext message on output. There must + * be at least 15 bytes of space in this buffer even if the caller expects + * to receive less data than that. + * \param mlen Receives the length of the plaintext message on output. + * \param nsec Secret nonce - not used by this algorithm. + * \param c Buffer that contains the ciphertext to decrypt. + * \param clen Length of the input data in bytes, which must be 32. + * \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, which must be zero. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to decrypt the packet. + * + * \return 0 on success, -1 if the authentication tag was incorrect, + * or -2 if the caller supplied associated data. + * + * \sa saturnin_short_aead_encrypt() + */ +int saturnin_short_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); + +/** + * \brief Hashes a block of input data with SATURNIN to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * SATURNIN_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 saturnin_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an SATURNIN-Hash hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa saturnin_hash_update(), saturnin_hash_finalize(), saturnin_hash() + */ +void saturnin_hash_init(saturnin_hash_state_t *state); + +/** + * \brief Updates an SATURNIN-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. + * + * \sa saturnin_hash_init(), saturnin_hash_finalize() + */ +void saturnin_hash_update + (saturnin_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an SATURNIN-Hash hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa saturnin_hash_init(), saturnin_hash_update() + */ +void saturnin_hash_finalize + (saturnin_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.c b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.h b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/api.h b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/api.h new file mode 100644 index 0000000..75fabd7 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 32 +#define CRYPTO_NOOVERLAP 1 diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/encrypt.c b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/encrypt.c new file mode 100644 index 0000000..29d7d06 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "saturnin.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 saturnin_short_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 saturnin_short_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/internal-util.h b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.c b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.c new file mode 100644 index 0000000..734fc69 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.c @@ -0,0 +1,781 @@ +/* + * 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 "saturnin.h" +#include "internal-util.h" +#include + +aead_cipher_t const saturnin_cipher = { + "SATURNIN-CTR-Cascade", + SATURNIN_KEY_SIZE, + SATURNIN_NONCE_SIZE, + SATURNIN_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + saturnin_aead_encrypt, + saturnin_aead_decrypt +}; + +aead_cipher_t const saturnin_short_cipher = { + "SATURNIN-Short", + SATURNIN_KEY_SIZE, + SATURNIN_NONCE_SIZE, + SATURNIN_TAG_SIZE, + AEAD_FLAG_NONE, + saturnin_short_aead_encrypt, + saturnin_short_aead_decrypt +}; + +aead_hash_algorithm_t const saturnin_hash_algorithm = { + "SATURNIN-Hash", + sizeof(saturnin_hash_state_t), + SATURNIN_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + saturnin_hash, + (aead_hash_init_t)saturnin_hash_init, + (aead_hash_update_t)saturnin_hash_update, + (aead_hash_finalize_t)saturnin_hash_finalize, + 0, /* absorb */ + 0 /* squeeze */ +}; + +/* Round constant tables for various combinations of rounds and domain_sep */ +static uint32_t const RC_10_1[] = { + 0x4eb026c2, 0x90595303, 0xaa8fe632, 0xfe928a92, 0x4115a419, + 0x93539532, 0x5db1cc4e, 0x541515ca, 0xbd1f55a8, 0x5a6e1a0d +}; +static uint32_t const RC_10_2[] = { + 0x4e4526b5, 0xa3565ff0, 0x0f8f20d8, 0x0b54bee1, 0x7d1a6c9d, + 0x17a6280a, 0xaa46c986, 0xc1199062, 0x182c5cde, 0xa00d53fe +}; +static uint32_t const RC_10_3[] = { + 0x4e162698, 0xb2535ba1, 0x6c8f9d65, 0x5816ad30, 0x691fd4fa, + 0x6bf5bcf9, 0xf8eb3525, 0xb21decfa, 0x7b3da417, 0xf62c94b4 +}; +static uint32_t const RC_10_4[] = { + 0x4faf265b, 0xc5484616, 0x45dcad21, 0xe08bd607, 0x0504fdb8, + 0x1e1f5257, 0x45fbc216, 0xeb529b1f, 0x52194e32, 0x5498c018 +}; +static uint32_t const RC_10_5[] = { + 0x4ffc2676, 0xd44d4247, 0x26dc109c, 0xb3c9c5d6, 0x110145df, + 0x624cc6a4, 0x17563eb5, 0x9856e787, 0x3108b6fb, 0x02b90752 +}; +static uint32_t const RC_10_6[] = { + 0x4f092601, 0xe7424eb4, 0x83dcd676, 0x460ff1a5, 0x2d0e8d5b, + 0xe6b97b9c, 0xe0a13b7d, 0x0d5a622f, 0x943bbf8d, 0xf8da4ea1 +}; +static uint32_t const RC_16_7[] = { + 0x3fba180c, 0x563ab9ab, 0x125ea5ef, 0x859da26c, 0xb8cf779b, + 0x7d4de793, 0x07efb49f, 0x8d525306, 0x1e08e6ab, 0x41729f87, + 0x8c4aef0a, 0x4aa0c9a7, 0xd93a95ef, 0xbb00d2af, 0xb62c5bf0, + 0x386d94d8 +}; +static uint32_t const RC_16_8[] = { + 0x3c9b19a7, 0xa9098694, 0x23f878da, 0xa7b647d3, 0x74fc9d78, + 0xeacaae11, 0x2f31a677, 0x4cc8c054, 0x2f51ca05, 0x5268f195, + 0x4f5b8a2b, 0xf614b4ac, 0xf1d95401, 0x764d2568, 0x6a493611, + 0x8eef9c3e +}; + +/* Rotate the 4-bit nibbles within a 16-bit word left */ +#define leftRotate4_N(a, mask1, bits1, mask2, bits2) \ + do { \ + uint32_t _temp = (a); \ + (a) = ((_temp & (mask1)) << (bits1)) | \ + ((_temp & ((mask1) ^ (uint32_t)0xFFFFU)) >> (4 - (bits1))) | \ + ((_temp & (((uint32_t)(mask2)) << 16)) << (bits2)) | \ + ((_temp & (((uint32_t)((mask2)) << 16) ^ 0xFFFF0000U)) >> (4 - (bits2))); \ + } while (0) + +/* Rotate 16-bit subwords left */ +#define leftRotate16_N(a, mask1, bits1, mask2, bits2) \ + do { \ + uint32_t _temp = (a); \ + (a) = ((_temp & (mask1)) << (bits1)) | \ + ((_temp & ((mask1) ^ (uint32_t)0xFFFFU)) >> (16 - (bits1))) | \ + ((_temp & (((uint32_t)(mask2)) << 16)) << (bits2)) | \ + ((_temp & (((uint32_t)((mask2)) << 16) ^ 0xFFFF0000U)) >> (16 - (bits2))); \ + } while (0) + +/* XOR the SATURNIN state with the key */ +#define saturnin_xor_key() \ + do { \ + for (index = 0; index < 8; ++index) \ + S[index] ^= K[index]; \ + } while (0) + +/* XOR the SATURNIN state with a rotated version of the key */ +#define saturnin_xor_key_rotated() \ + do { \ + for (index = 0; index < 8; ++index) \ + S[index] ^= K[index + 8]; \ + } while (0) + +/* Apply an SBOX layer for SATURNIN - definition from the specification */ +#define S_LAYER(a, b, c, d) \ + do { \ + (a) ^= (b) & (c); \ + (b) ^= (a) | (d); \ + (d) ^= (b) | (c); \ + (c) ^= (b) & (d); \ + (b) ^= (a) | (c); \ + (a) ^= (b) | (d); \ + } while (0) + +/* Apply an SBOX layer for SATURNIN in reverse */ +#define S_LAYER_INVERSE(a, b, c, d) \ + do { \ + (a) ^= (b) | (d); \ + (b) ^= (a) | (c); \ + (c) ^= (b) & (d); \ + (d) ^= (b) | (c); \ + (b) ^= (a) | (d); \ + (a) ^= (b) & (c); \ + } while (0) + +/** + * \brief Applies the SBOX to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sbox(uint32_t S[8]) +{ + uint32_t a, b, c, d; + + /* PI_0 on the first half of the state */ + a = S[0]; b = S[1]; c = S[2]; d = S[3]; + S_LAYER(a, b, c, d); + S[0] = b; S[1] = c; S[2] = d; S[3] = a; + + /* PI_1 on the second half of the state */ + a = S[4]; b = S[5]; c = S[6]; d = S[7]; + S_LAYER(a, b, c, d); + S[4] = d; S[5] = b; S[6] = a; S[7] = c; +} + +/** + * \brief Applies the inverse of the SBOX to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sbox_inverse(uint32_t S[8]) +{ + uint32_t a, b, c, d; + + /* PI_0 on the first half of the state */ + b = S[0]; c = S[1]; d = S[2]; a = S[3]; + S_LAYER_INVERSE(a, b, c, d); + S[0] = a; S[1] = b; S[2] = c; S[3] = d; + + /* PI_1 on the second half of the state */ + d = S[4]; b = S[5]; a = S[6]; c = S[7]; + S_LAYER_INVERSE(a, b, c, d); + S[4] = a; S[5] = b; S[6] = c; S[7] = d; +} + +/** + * \brief Applies the MDS matrix to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_mds(uint32_t S[8]) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t tmp; + + /* Load the state into temporary working variables */ + x0 = S[0]; x1 = S[1]; x2 = S[2]; x3 = S[3]; + x4 = S[4]; x5 = S[5]; x6 = S[6]; x7 = S[7]; + + /* Apply the MDS matrix to the state */ + #define SWAP(a) (((a) << 16) | ((a) >> 16)) + #define MUL(x0, x1, x2, x3, tmp) \ + do { \ + tmp = x0; x0 = x1; x1 = x2; x2 = x3; x3 = tmp ^ x0; \ + } while (0) + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + MUL(x4, x5, x6, x7, tmp); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + MUL(x0, x1, x2, x3, tmp); + MUL(x0, x1, x2, x3, tmp); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + + /* Store the temporary working variables back into the state */ + S[0] = x0; S[1] = x1; S[2] = x2; S[3] = x3; + S[4] = x4; S[5] = x5; S[6] = x6; S[7] = x7; +} + +/** + * \brief Applies the inverse of the MDS matrix to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_mds_inverse(uint32_t S[8]) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t tmp; + + /* Load the state into temporary working variables */ + x0 = S[0]; x1 = S[1]; x2 = S[2]; x3 = S[3]; + x4 = S[4]; x5 = S[5]; x6 = S[6]; x7 = S[7]; + + /* Apply the inverse of the MDS matrix to the state */ + #define MULINV(x0, x1, x2, x3, tmp) \ + do { \ + tmp = x3; x3 = x2; x2 = x1; x1 = x0; x0 = x1 ^ tmp; \ + } while (0) + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + MULINV(x0, x1, x2, x3, tmp); + MULINV(x0, x1, x2, x3, tmp); + x6 ^= SWAP(x2); x7 ^= SWAP(x3); + x4 ^= SWAP(x0); x5 ^= SWAP(x1); + MULINV(x4, x5, x6, x7, tmp); + x0 ^= x4; x1 ^= x5; x2 ^= x6; x3 ^= x7; + + /* Store the temporary working variables back into the state */ + S[0] = x0; S[1] = x1; S[2] = x2; S[3] = x3; + S[4] = x4; S[5] = x5; S[6] = x6; S[7] = x7; +} + +/** + * \brief Applies the slice permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_slice(uint32_t S[8]) +{ + leftRotate4_N(S[0], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[1], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[2], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[3], 0xFFFFU, 0, 0x3333, 2); + + leftRotate4_N(S[4], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[5], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[6], 0x7777U, 1, 0x1111, 3); + leftRotate4_N(S[7], 0x7777U, 1, 0x1111, 3); +} + +/** + * \brief Applies the inverse of the slice permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_slice_inverse(uint32_t S[8]) +{ + leftRotate4_N(S[0], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[1], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[2], 0xFFFFU, 0, 0x3333, 2); + leftRotate4_N(S[3], 0xFFFFU, 0, 0x3333, 2); + + leftRotate4_N(S[4], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[5], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[6], 0x1111U, 3, 0x7777, 1); + leftRotate4_N(S[7], 0x1111U, 3, 0x7777, 1); +} + +/** + * \brief Applies the sheet permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sheet(uint32_t S[8]) +{ + leftRotate16_N(S[0], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[1], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[2], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[3], 0xFFFFU, 0, 0x00FF, 8); + + leftRotate16_N(S[4], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[5], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[6], 0x0FFFU, 4, 0x000F, 12); + leftRotate16_N(S[7], 0x0FFFU, 4, 0x000F, 12); +} + +/** + * \brief Applies the inverse of the sheet permutation to the SATURNIN state. + * + * \param S The state. + */ +static void saturnin_sheet_inverse(uint32_t S[8]) +{ + leftRotate16_N(S[0], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[1], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[2], 0xFFFFU, 0, 0x00FF, 8); + leftRotate16_N(S[3], 0xFFFFU, 0, 0x00FF, 8); + + leftRotate16_N(S[4], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[5], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[6], 0x000FU, 12, 0x0FFF, 4); + leftRotate16_N(S[7], 0x000FU, 12, 0x0FFF, 4); +} + +/** + * \brief Encrypts a 256-bit block with the SATURNIN block cipher. + * + * \param output Ciphertext output block, 32 bytes. + * \param input Plaintext input block, 32 bytes. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + * + * The \a input and \a output buffers can be the same. + * + * \sa saturnin_block_decrypt() + */ +static void saturnin_block_encrypt + (unsigned char *output, const unsigned char *input, + const unsigned char *key, unsigned rounds, const uint32_t *RC) +{ + uint32_t K[16]; + uint32_t S[8]; + uint32_t temp; + unsigned index; + + /* Unpack the key and the input block */ + for (index = 0; index < 16; index += 2) { + temp = ((uint32_t)(key[index])) | + (((uint32_t)(key[index + 1])) << 8) | + (((uint32_t)(key[index + 16])) << 16) | + (((uint32_t)(key[index + 17])) << 24); + K[index / 2] = temp; + K[8 + (index / 2)] = ((temp & 0x001F001FU) << 11) | + ((temp >> 5) & 0x07FF07FFU); + S[index / 2] = ((uint32_t)(input[index])) | + (((uint32_t)(input[index + 1])) << 8) | + (((uint32_t)(input[index + 16])) << 16) | + (((uint32_t)(input[index + 17])) << 24); + } + + /* XOR the key into the state */ + saturnin_xor_key(); + + /* Perform all encryption rounds */ + for (; rounds > 0; rounds -= 2, RC += 2) { + saturnin_sbox(S); + saturnin_mds(S); + saturnin_sbox(S); + saturnin_slice(S); + saturnin_mds(S); + saturnin_slice_inverse(S); + S[0] ^= RC[0]; + saturnin_xor_key_rotated(); + + saturnin_sbox(S); + saturnin_mds(S); + saturnin_sbox(S); + saturnin_sheet(S); + saturnin_mds(S); + saturnin_sheet_inverse(S); + S[0] ^= RC[1]; + saturnin_xor_key(); + } + + /* Encode the state into the output block */ + for (index = 0; index < 16; index += 2) { + temp = S[index / 2]; + output[index] = (uint8_t)temp; + output[index + 1] = (uint8_t)(temp >> 8); + output[index + 16] = (uint8_t)(temp >> 16); + output[index + 17] = (uint8_t)(temp >> 24); + } +} + +/** + * \brief Decrypts a 256-bit block with the SATURNIN block cipher. + * + * \param output Plaintext output block, 32 bytes. + * \param input Ciphertext input block, 32 bytes. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + * + * The \a input and \a output buffers can be the same. + * + * \sa saturnin_block_encrypt() + */ +static void saturnin_block_decrypt + (unsigned char *output, const unsigned char *input, + const unsigned char *key, unsigned rounds, const uint32_t *RC) +{ + uint32_t K[16]; + uint32_t S[8]; + uint32_t temp; + unsigned index; + + /* Unpack the key and the input block */ + for (index = 0; index < 16; index += 2) { + temp = ((uint32_t)(key[index])) | + (((uint32_t)(key[index + 1])) << 8) | + (((uint32_t)(key[index + 16])) << 16) | + (((uint32_t)(key[index + 17])) << 24); + K[index / 2] = temp; + K[8 + (index / 2)] = ((temp & 0x001F001FU) << 11) | + ((temp >> 5) & 0x07FF07FFU); + S[index / 2] = ((uint32_t)(input[index])) | + (((uint32_t)(input[index + 1])) << 8) | + (((uint32_t)(input[index + 16])) << 16) | + (((uint32_t)(input[index + 17])) << 24); + } + + /* Perform all decryption rounds */ + RC += rounds - 2; + for (; rounds > 0; rounds -= 2, RC -= 2) { + saturnin_xor_key(); + S[0] ^= RC[1]; + saturnin_sheet(S); + saturnin_mds_inverse(S); + saturnin_sheet_inverse(S); + saturnin_sbox_inverse(S); + saturnin_mds_inverse(S); + saturnin_sbox_inverse(S); + + saturnin_xor_key_rotated(); + S[0] ^= RC[0]; + saturnin_slice(S); + saturnin_mds_inverse(S); + saturnin_slice_inverse(S); + saturnin_sbox_inverse(S); + saturnin_mds_inverse(S); + saturnin_sbox_inverse(S); + } + + /* XOR the key into the state */ + saturnin_xor_key(); + + /* Encode the state into the output block */ + for (index = 0; index < 16; index += 2) { + temp = S[index / 2]; + output[index] = (uint8_t)temp; + output[index + 1] = (uint8_t)(temp >> 8); + output[index + 16] = (uint8_t)(temp >> 16); + output[index + 17] = (uint8_t)(temp >> 24); + } +} + +/** + * \brief Encrypts a 256-bit block with the SATURNIN block cipher and + * then XOR's itself to generate a new key. + * + * \param block Block to be encrypted and then XOR'ed with itself. + * \param key Points to the 32 byte key for the block cipher. + * \param rounds Number of rounds to perform. + * \param RC Round constants to use for domain separation. + */ +void saturnin_block_encrypt_xor + (const unsigned char *block, unsigned char *key, + unsigned rounds, const uint32_t *RC) +{ + unsigned char temp[32]; + saturnin_block_encrypt(temp, block, key, rounds, RC); + lw_xor_block_2_src(key, block, temp, 32); +} + +/** + * \brief Encrypts (or decrypts) a data packet in CTR mode. + * + * \param c Output ciphertext buffer. + * \param m Input plaintext buffer. + * \param mlen Length of the plaintext in bytes. + * \param k Points to the 32-byte key. + * \param block Points to the pre-formatted nonce block. + */ +static void saturnin_ctr_encrypt + (unsigned char *c, const unsigned char *m, unsigned long long mlen, + const unsigned char *k, unsigned char *block) +{ + /* Note: Specification requires a 95-bit counter but we only use 32-bit. + * This limits the maximum packet size to 128Gb. That should be OK */ + uint32_t counter = 1; + unsigned char out[32]; + while (mlen >= 32) { + be_store_word32(block + 28, counter); + saturnin_block_encrypt(out, block, k, 10, RC_10_1); + lw_xor_block_2_src(c, out, m, 32); + c += 32; + m += 32; + mlen -= 32; + ++counter; + } + if (mlen > 0) { + be_store_word32(block + 28, counter); + saturnin_block_encrypt(out, block, k, 10, RC_10_1); + lw_xor_block_2_src(c, out, m, (unsigned)mlen); + } +} + +/** + * \brief Pads an authenticates a message. + * + * \param tag Points to the authentication tag. + * \param block Temporary block of 32 bytes from the caller. + * \param m Points to the message to be authenticated. + * \param mlen Length of the message to be authenticated in bytes. + * \param rounds Number of rounds to perform. + * \param RC1 Round constants to use for domain separation on full blocks. + * \param RC2 Round constants to use for domain separation on the last block. + */ +static void saturnin_authenticate + (unsigned char *tag, unsigned char *block, + const unsigned char *m, unsigned long long mlen, + unsigned rounds, const uint32_t *RC1, const uint32_t *RC2) +{ + unsigned temp; + while (mlen >= 32) { + saturnin_block_encrypt_xor(m, tag, rounds, RC1); + m += 32; + mlen -= 32; + } + temp = (unsigned)mlen; + memcpy(block, m, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, 31 - temp); + saturnin_block_encrypt_xor(block, tag, rounds, RC2); +} + +int saturnin_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) +{ + unsigned char block[32]; + unsigned char *tag; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SATURNIN_TAG_SIZE; + + /* Format the input block from the padded nonce */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + + /* Encrypt the plaintext in counter mode to produce the ciphertext */ + saturnin_ctr_encrypt(c, m, mlen, k, block); + + /* Set the counter back to zero and then encrypt the nonce */ + tag = c + mlen; + memcpy(tag, k, 32); + memset(block + 17, 0, 15); + saturnin_block_encrypt_xor(block, tag, 10, RC_10_2); + + /* Authenticate the associated data and the ciphertext */ + saturnin_authenticate(tag, block, ad, adlen, 10, RC_10_2, RC_10_3); + saturnin_authenticate(tag, block, c, mlen, 10, RC_10_4, RC_10_5); + return 0; +} + +int saturnin_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) +{ + unsigned char block[32]; + unsigned char tag[32]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SATURNIN_TAG_SIZE) + return -1; + *mlen = clen - SATURNIN_TAG_SIZE; + + /* Format the input block from the padded nonce */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + + /* Encrypt the nonce to initialize the authentication phase */ + memcpy(tag, k, 32); + saturnin_block_encrypt_xor(block, tag, 10, RC_10_2); + + /* Authenticate the associated data and the ciphertext */ + saturnin_authenticate(tag, block, ad, adlen, 10, RC_10_2, RC_10_3); + saturnin_authenticate(tag, block, c, *mlen, 10, RC_10_4, RC_10_5); + + /* Decrypt the ciphertext in counter mode to produce the plaintext */ + memcpy(block, npub, 16); + block[16] = 0x80; + memset(block + 17, 0, 15); + saturnin_ctr_encrypt(m, c, *mlen, k, block); + + /* Check the authentication tag at the end of the message */ + return aead_check_tag + (m, *mlen, tag, c + *mlen, SATURNIN_TAG_SIZE); +} + +int saturnin_short_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) +{ + unsigned char block[32]; + unsigned temp; + (void)nsec; + (void)ad; + + /* Validate the parameters: no associated data allowed and m <= 15 bytes */ + if (adlen > 0 || mlen > 15) + return -2; + + /* Format the input block from the nonce and plaintext */ + temp = (unsigned)mlen; + memcpy(block, npub, 16); + memcpy(block + 16, m, temp); + block[16 + temp] = 0x80; /* Padding */ + memset(block + 17 + temp, 0, 15 - temp); + + /* Encrypt the input block to produce the output ciphertext */ + saturnin_block_encrypt(c, block, k, 10, RC_10_6); + *clen = 32; + return 0; +} + +int saturnin_short_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) +{ + unsigned char block[32]; + unsigned check1, check2, len; + int index, result; + (void)nsec; + (void)ad; + + /* Validate the parameters: no associated data and c is always 32 bytes */ + if (adlen > 0) + return -2; + if (clen != 32) + return -1; + + /* Decrypt the ciphertext block */ + saturnin_block_decrypt(block, c, k, 10, RC_10_6); + + /* Verify that the output block starts with the nonce and that it is + * padded correctly. We need to do this very carefully to avoid leaking + * any information that could be used in a padding oracle attack. Use the + * same algorithm as the reference implementation of SATURNIN-Short */ + check1 = 0; + for (index = 0; index < 16; ++index) + check1 |= npub[index] ^ block[index]; + check2 = 0xFF; + len = 0; + for (index = 15; index >= 0; --index) { + unsigned temp = block[16 + index]; + unsigned temp2 = check2 & -(1 - (((temp ^ 0x80) + 0xFF) >> 8)); + len |= temp2 & (unsigned)index; + check2 &= ~temp2; + check1 |= check2 & ((temp + 0xFF) >> 8); + } + check1 |= check2; + + /* At this point, check1 is zero if the nonce and plaintext are good, + * or non-zero if there was an error in the decrypted data */ + result = (((int)check1) - 1) >> 8; + + /* The "result" is -1 if the data is good or zero if the data is invalid. + * Copy either the plaintext or zeroes to the output buffer. We assume + * that the output buffer has space for up to 15 bytes. This may return + * some of the padding to the caller but as long as they restrict + * themselves to the first *mlen bytes then it shouldn't be a problem */ + for (index = 0; index < 15; ++index) + m[index] = block[16 + index] & result; + *mlen = len; + return ~result; +} + +int saturnin_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + unsigned char tag[32]; + unsigned char block[32]; + memset(tag, 0, sizeof(tag)); + saturnin_authenticate(tag, block, in, inlen, 16, RC_16_7, RC_16_8); + memcpy(out, tag, 32); + return 0; +} + +void saturnin_hash_init(saturnin_hash_state_t *state) +{ + memset(state, 0, sizeof(saturnin_hash_state_t)); +} + +void saturnin_hash_update + (saturnin_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + unsigned temp; + + /* Handle the partial left-over block from last time */ + if (state->s.count) { + temp = 32 - state->s.count; + if (temp > inlen) { + temp = (unsigned)inlen; + memcpy(state->s.block + state->s.count, in, temp); + state->s.count += temp; + return; + } + memcpy(state->s.block + state->s.count, in, temp); + state->s.count = 0; + in += temp; + inlen -= temp; + saturnin_block_encrypt_xor(state->s.block, state->s.hash, 16, RC_16_7); + } + + /* Process full blocks that are aligned at state->s.count == 0 */ + while (inlen >= 32) { + saturnin_block_encrypt_xor(in, state->s.hash, 16, RC_16_7); + in += 32; + inlen -= 32; + } + + /* Process the left-over block at the end of the input */ + temp = (unsigned)inlen; + memcpy(state->s.block, in, temp); + state->s.count = temp; +} + +void saturnin_hash_finalize + (saturnin_hash_state_t *state, unsigned char *out) +{ + /* Pad the final block */ + state->s.block[state->s.count] = 0x80; + memset(state->s.block + state->s.count + 1, 0, 31 - state->s.count); + + /* Generate the final hash value */ + saturnin_block_encrypt_xor(state->s.block, state->s.hash, 16, RC_16_8); + memcpy(out, state->s.hash, 32); +} diff --git a/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.h b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.h new file mode 100644 index 0000000..873d950 --- /dev/null +++ b/saturnin/Implementations/crypto_aead/saturninshortv2/rhys/saturnin.h @@ -0,0 +1,270 @@ +/* + * 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_SATURNIN_H +#define LWCRYPTO_SATURNIN_H + +#include "aead-common.h" + +/** + * \file saturnin.h + * \brief Saturnin authenticated encryption algorithm. + * + * The Saturnin family consists of two members: SATURNIN-CTR-Cascade and + * SATURNIN-Short. Both take a 256-bit key and a 128-bit nonce. + * Internally they use a 256-bit block cipher similar in construction to AES. + * + * SATURNIN-Short does not support associated data or plaintext packets + * with more than 15 bytes. This makes it very efficient on short packets + * with only a single block operation involved. + * + * This implementation of SATURNIN-Short will return an error if the + * caller supplies associated data or more than 15 bytes of plaintext. + * + * References: https://project.inria.fr/saturnin/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SATURNIN family members. + */ +#define SATURNIN_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for SATURNIN-CTR-Cascade or the + * total size of the ciphertext for SATURNIN-Short. + */ +#define SATURNIN_TAG_SIZE 32 + +/** + * \brief Size of the nonce for all SATURNIN family members. + */ +#define SATURNIN_NONCE_SIZE 16 + +/** + * \brief Size of the hash for SATURNIN-Hash. + */ +#define SATURNIN_HASH_SIZE 32 + +/** + * \brief State information for SATURNIN-Hash incremental modes. + */ +typedef union +{ + struct { + unsigned char hash[32]; /**< Current hash state */ + unsigned char block[32]; /**< Left-over block data from last update */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: 0 for absorb, 1 for squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} saturnin_hash_state_t; + +/** + * \brief Meta-information block for the SATURNIN-CTR-Cascade cipher. + */ +extern aead_cipher_t const saturnin_cipher; + +/** + * \brief Meta-information block for the SATURNIN-Short cipher. + */ +extern aead_cipher_t const saturnin_short_cipher; + +/** + * \brief Meta-information block for SATURNIN-Hash. + */ +extern aead_hash_algorithm_t const saturnin_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with SATURNIN-CTR-Cascade. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 32 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa saturnin_aead_decrypt() + */ +int saturnin_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); + +/** + * \brief Decrypts and authenticates a packet with SATURNIN-CTR-Cascade. + * + * \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 - not used by this algorithm. + * \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 32 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa saturnin_aead_encrypt() + */ +int saturnin_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); + +/** + * \brief Encrypts and authenticates a packet with SATURNIN-Short. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which is always 32. + * \param m Buffer that contains the plaintext message to encrypt. + * \param mlen Length of the plaintext message in bytes, which must be + * less than or equal to 15 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, which must be zero. + * \param nsec Secret nonce - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or -2 if the caller supplied too many bytes of + * plaintext or they supplied associated data. + * + * \sa saturnin_short_aead_decrypt() + */ +int saturnin_short_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); + +/** + * \brief Decrypts and authenticates a packet with SATURNIN-Short. + * + * \param m Buffer to receive the plaintext message on output. There must + * be at least 15 bytes of space in this buffer even if the caller expects + * to receive less data than that. + * \param mlen Receives the length of the plaintext message on output. + * \param nsec Secret nonce - not used by this algorithm. + * \param c Buffer that contains the ciphertext to decrypt. + * \param clen Length of the input data in bytes, which must be 32. + * \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, which must be zero. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to decrypt the packet. + * + * \return 0 on success, -1 if the authentication tag was incorrect, + * or -2 if the caller supplied associated data. + * + * \sa saturnin_short_aead_encrypt() + */ +int saturnin_short_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); + +/** + * \brief Hashes a block of input data with SATURNIN to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * SATURNIN_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 saturnin_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an SATURNIN-Hash hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa saturnin_hash_update(), saturnin_hash_finalize(), saturnin_hash() + */ +void saturnin_hash_init(saturnin_hash_state_t *state); + +/** + * \brief Updates an SATURNIN-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. + * + * \sa saturnin_hash_init(), saturnin_hash_finalize() + */ +void saturnin_hash_update + (saturnin_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an SATURNIN-Hash hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa saturnin_hash_init(), saturnin_hash_update() + */ +void saturnin_hash_finalize + (saturnin_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/encrypt.c new file mode 100644 index 0000000..64c6ea2 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m5_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_m5_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk296128v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/encrypt.c new file mode 100644 index 0000000..d304a40 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m6_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_m6_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk29664v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/encrypt.c new file mode 100644 index 0000000..00e9d2e --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk3128128v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/api.h new file mode 100644 index 0000000..4bf8f5c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/encrypt.c new file mode 100644 index 0000000..db41b19 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m3_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_m3_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk312864v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/encrypt.c new file mode 100644 index 0000000..92605fe --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m2_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_m2_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk396128v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.c b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/api.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/encrypt.c b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/encrypt.c new file mode 100644 index 0000000..0623826 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#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_m4_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_m4_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.c b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.c new file mode 100644 index 0000000..65ba4ed --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.c @@ -0,0 +1,811 @@ +/* + * 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 "internal-skinny128.h" +#include "internal-skinnyutil.h" +#include "internal-util.h" +#include + +STATIC_INLINE void skinny128_fast_forward_tk(uint32_t *tk) +{ + /* This function is used to fast-forward the TK1 tweak value + * to the value at the end of the key schedule for decryption. + * + * The tweak permutation repeats every 16 rounds, so SKINNY-128-256 + * with 48 rounds does not need any fast forwarding applied. + * SKINNY-128-128 with 40 rounds and SKINNY-128-384 with 56 rounds + * are equivalent to applying the permutation 8 times: + * + * PT*8 = [5, 6, 3, 2, 7, 0, 1, 4, 13, 14, 11, 10, 15, 8, 9, 12] + */ + uint32_t row0 = tk[0]; + uint32_t row1 = tk[1]; + uint32_t row2 = tk[2]; + uint32_t row3 = tk[3]; + tk[0] = ((row1 >> 8) & 0x0000FFFFU) | + ((row0 >> 8) & 0x00FF0000U) | + ((row0 << 8) & 0xFF000000U); + tk[1] = ((row1 >> 24) & 0x000000FFU) | + ((row0 << 8) & 0x00FFFF00U) | + ((row1 << 24) & 0xFF000000U); + tk[2] = ((row3 >> 8) & 0x0000FFFFU) | + ((row2 >> 8) & 0x00FF0000U) | + ((row2 << 8) & 0xFF000000U); + tk[3] = ((row3 >> 24) & 0x000000FFU) | + ((row2 << 8) & 0x00FFFF00U) | + ((row3 << 24) & 0xFF000000U); +} + +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 32 && key_len != 48)) + return 0; + + /* Set the initial states of TK1, TK2, and TK3 */ + if (key_len == 32) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + TK3[0] = le_load_word32(key + 16); + TK3[1] = le_load_word32(key + 20); + TK3[2] = le_load_word32(key + 24); + TK3[3] = le_load_word32(key + 28); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + } + + /* Set up the key schedule using TK2 and TK3. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ TK3[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ TK3[1] ^ (rc >> 4); + + /* Permute TK2 and TK3 for the next round */ + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + + /* Apply the LFSR's to TK2 and TK3 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + return 1; +} + +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_384_encrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_decrypt + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Permute TK1 to fast-forward it to the end of the key schedule */ + skinny128_fast_forward_tk(TK1); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_384_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk2 + (const skinny_128_384_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, const unsigned char *tk2) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1/TK2 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + TK2[0] = le_load_word32(tk2); + TK2[1] = le_load_word32(tk2 + 4); + TK2[2] = le_load_word32(tk2 + 8); + TK2[3] = le_load_word32(tk2 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0] ^ TK2[0]; + s1 ^= schedule[1] ^ TK1[1] ^ TK2[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_384_encrypt_tk_full + (const unsigned char key[48], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t TK3[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + TK3[0] = le_load_word32(key + 32); + TK3[1] = le_load_word32(key + 36); + TK3[2] = le_load_word32(key + 40); + TK3[3] = le_load_word32(key + 44); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_384_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ TK3[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ TK3[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1, TK2, and TK3 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_permute_tk(TK3); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + skinny128_LFSR3(TK3[0]); + skinny128_LFSR3(TK3[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK2[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || (key_len != 16 && key_len != 32)) + return 0; + + /* Set the initial states of TK1 and TK2 */ + if (key_len == 16) { + memset(ks->TK1, 0, sizeof(ks->TK1)); + TK2[0] = le_load_word32(key); + TK2[1] = le_load_word32(key + 4); + TK2[2] = le_load_word32(key + 8); + TK2[3] = le_load_word32(key + 12); + } else { + memcpy(ks->TK1, key, 16); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + } + + /* Set up the key schedule using TK2. TK1 is not added + * to the key schedule because we will derive that part of the + * schedule during encryption operations */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK2[0] ^ (rc & 0x0F); + schedule[1] = TK2[1] ^ (rc >> 4); + + /* Permute TK2 for the next round */ + skinny128_permute_tk(TK2); + + /* Apply the LFSR to TK2 */ + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + return 1; +} + +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len) +{ + /* Validate the parameters */ + if (!ks || !tweak || tweak_len != 16) + return 0; + + /* Set TK1 directly from the tweak value */ + memcpy(ks->TK1, tweak, 16); + return 1; +} + +void skinny_128_256_encrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1 */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_decrypt + (const skinny_128_256_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakable part of the state, TK1. + * There is no need to fast-forward TK1 because the value at + * the end of the key schedule is the same as at the start */ + TK1[0] = le_load_word32(ks->TK1); + TK1[1] = le_load_word32(ks->TK1 + 4); + TK1[2] = le_load_word32(ks->TK1 + 8); + TK1[3] = le_load_word32(ks->TK1 + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_256_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round, schedule -= 2) { + /* Inverse permutation on TK1 for this round */ + skinny128_inv_permute_tk(TK1); + + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0] ^ TK1[0]; + s1 ^= schedule[1] ^ TK1[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_256_encrypt_tk_full + (const unsigned char key[32], unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + uint32_t TK1[4]; + uint32_t TK2[4]; + uint32_t temp; + unsigned round; + uint8_t rc = 0; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Make a local copy of the tweakey */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + TK2[0] = le_load_word32(key + 16); + TK2[1] = le_load_word32(key + 20); + TK2[2] = le_load_word32(key + 24); + TK2[3] = le_load_word32(key + 28); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_256_ROUNDS; ++round) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* XOR the round constant and the subkey for this round */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + s0 ^= TK1[0] ^ TK2[0] ^ (rc & 0x0F); + s1 ^= TK1[1] ^ TK2[1] ^ (rc >> 4); + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + + /* Permute TK1 and TK2 for the next round */ + skinny128_permute_tk(TK1); + skinny128_permute_tk(TK2); + skinny128_LFSR2(TK2[0]); + skinny128_LFSR2(TK2[1]); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len) +{ + uint32_t TK1[4]; + uint32_t *schedule; + unsigned round; + uint8_t rc; + + /* Validate the parameters */ + if (!ks || !key || key_len != 16) + return 0; + + /* Set the initial state of TK1 */ + TK1[0] = le_load_word32(key); + TK1[1] = le_load_word32(key + 4); + TK1[2] = le_load_word32(key + 8); + TK1[3] = le_load_word32(key + 12); + + /* Set up the key schedule using TK1 */ + schedule = ks->k; + rc = 0; + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* XOR the round constants with the current schedule words. + * The round constants for the 3rd and 4th rows are + * fixed and will be applied during encryption. */ + rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01; + rc &= 0x3F; + schedule[0] = TK1[0] ^ (rc & 0x0F); + schedule[1] = TK1[1] ^ (rc >> 4); + + /* Permute TK1 for the next round */ + skinny128_permute_tk(TK1); + } + return 1; +} + +void skinny_128_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule = ks->k; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all encryption rounds */ + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule += 2) { + /* Apply the S-box to all bytes in the state */ + skinny128_sbox(s0); + skinny128_sbox(s1); + skinny128_sbox(s2); + skinny128_sbox(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Shift the cells in the rows right, which moves the cell + * values up closer to the MSB. That is, we do a left rotate + * on the word to rotate the cells in the word right */ + s1 = leftRotate8(s1); + s2 = leftRotate16(s2); + s3 = leftRotate24(s3); + + /* Mix the columns */ + s1 ^= s2; + s2 ^= s0; + temp = s3 ^ s2; + s3 = s2; + s2 = s1; + s1 = s0; + s0 = temp; + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} + +void skinny_128_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + const uint32_t *schedule; + uint32_t temp; + unsigned round; + + /* Unpack the input block into the state array */ + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all decryption rounds */ + schedule = &(ks->k[SKINNY_128_128_ROUNDS * 2 - 2]); + for (round = 0; round < SKINNY_128_128_ROUNDS; ++round, schedule -= 2) { + /* Inverse mix of the columns */ + temp = s3; + s3 = s0; + s0 = s1; + s1 = s2; + s3 ^= temp; + s2 = temp ^ s0; + s1 ^= s2; + + /* Inverse shift of the rows */ + s1 = leftRotate24(s1); + s2 = leftRotate16(s2); + s3 = leftRotate8(s3); + + /* Apply the subkey for this round */ + s0 ^= schedule[0]; + s1 ^= schedule[1]; + s2 ^= 0x02; + + /* Apply the inverse of the S-box to all bytes in the state */ + skinny128_inv_sbox(s0); + skinny128_inv_sbox(s1); + skinny128_inv_sbox(s2); + skinny128_inv_sbox(s3); + } + + /* Pack the result into the output buffer */ + le_store_word32(output, s0); + le_store_word32(output + 4, s1); + le_store_word32(output + 8, s2); + le_store_word32(output + 12, s3); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.h new file mode 100644 index 0000000..76b34f5 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinny128.h @@ -0,0 +1,315 @@ +/* + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_384_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 32 or 48, + * where 32 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-384. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_384_set_tweak + (skinny_128_384_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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. + */ +void skinny_128_384_encrypt_tk2 + (const 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]; + + /** Words of the key schedule */ + uint32_t k[SKINNY_128_256_ROUNDS * 2]; + +} 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. + * \param key_len Length of the key data, which must be 16 or 32, + * where 16 is used for the tweakable variant. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Sets the tweakable part of the key schedule for SKINNY-128-256. + * + * \param ks Points to the key schedule to modify. + * \param tweak Points to the tweak data. + * \param tweak_len Length of the tweak data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_256_set_tweak + (skinny_128_256_key_schedule_t *ks, const unsigned char *tweak, + size_t tweak_len); + +/** + * \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); + +/** + * \brief Number of rounds for SKINNY-128-128. + */ +#define SKINNY_128_128_ROUNDS 40 + +/** + * \brief Structure of the key schedule for SKINNY-128-128. + */ +typedef struct +{ + /** Words of the key schedule */ + uint32_t k[SKINNY_128_128_ROUNDS * 2]; + +} skinny_128_128_key_schedule_t; + +/** + * \brief Initializes the key schedule for SKINNY-128-128. + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int skinny_128_128_init + (skinny_128_128_key_schedule_t *ks, const unsigned char *key, + size_t key_len); + +/** + * \brief Encrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_encrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with SKINNY-128-128. + * + * \param ks Points to the SKINNY-128-128 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_128_decrypt + (const skinny_128_128_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinnyutil.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinnyutil.h new file mode 100644 index 0000000..83136cb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-skinnyutil.h @@ -0,0 +1,328 @@ +/* + * 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_SKINNYUTIL_H +#define LW_INTERNAL_SKINNYUTIL_H + +/** + * \file internal-skinnyutil.h + * \brief Utilities to help implement SKINNY and its variants. + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond skinnyutil */ + +/* Utilities for implementing SKINNY-128 */ + +#define skinny128_LFSR2(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x << 1) & 0xFEFEFEFEU) ^ \ + (((_x >> 7) ^ (_x >> 5)) & 0x01010101U); \ + } while (0) + + +#define skinny128_LFSR3(x) \ + do { \ + uint32_t _x = (x); \ + (x) = ((_x >> 1) & 0x7F7F7F7FU) ^ \ + (((_x << 7) ^ (_x << 1)) & 0x80808080U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny128_inv_LFSR2(x) skinny128_LFSR3(x) +#define skinny128_inv_LFSR3(x) skinny128_LFSR2(x) + +#define skinny128_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint32_t row2 = tk[2]; \ + uint32_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 16) | (row3 >> 16); \ + tk[0] = ((row2 >> 8) & 0x000000FFU) | \ + ((row2 << 16) & 0x00FF0000U) | \ + ( row3 & 0xFF00FF00U); \ + tk[1] = ((row2 >> 16) & 0x000000FFU) | \ + (row2 & 0xFF000000U) | \ + ((row3 << 8) & 0x0000FF00U) | \ + ( row3 & 0x00FF0000U); \ + } while (0) + +#define skinny128_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint32_t row0 = tk[0]; \ + uint32_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 >> 16) & 0x000000FFU) | \ + ((row0 << 8) & 0x0000FF00U) | \ + ((row1 << 16) & 0x00FF0000U) | \ + ( row1 & 0xFF000000U); \ + tk[3] = ((row0 >> 16) & 0x0000FF00U) | \ + ((row0 << 16) & 0xFF000000U) | \ + ((row1 >> 16) & 0x000000FFU) | \ + ((row1 << 8) & 0x00FF0000U); \ + } while (0) + +/* + * Apply the SKINNY sbox. The original version from the specification is + * equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE(x) + * ((((x) & 0x01010101U) << 2) | + * (((x) & 0x06060606U) << 5) | + * (((x) & 0x20202020U) >> 5) | + * (((x) & 0xC8C8C8C8U) >> 2) | + * (((x) & 0x10101010U) >> 1)) + * + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE(x); + * x = SBOX_MIX(x); + * return SBOX_SWAP(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + x ^= (((x >> 2) & (x >> 3)) & 0x11111111U); \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y; \ + y = (((x >> 5) & (x << 1)) & 0x04040404U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [2 7 6 1 3 0 4 5] */ \ + x = ((x & 0x08080808U) << 1) | \ + ((x & 0x32323232U) << 2) | \ + ((x & 0x01010101U) << 5) | \ + ((x & 0x80808080U) >> 6) | \ + ((x & 0x40404040U) >> 4) | \ + ((x & 0x04040404U) >> 2); \ +} while (0) + +/* + * Apply the inverse of the SKINNY sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x11111111U) ^ (x)) + * #define SBOX_SWAP(x) + * (((x) & 0xF9F9F9F9U) | + * (((x) >> 1) & 0x02020202U) | + * (((x) << 1) & 0x04040404U)) + * #define SBOX_PERMUTE_INV(x) + * ((((x) & 0x08080808U) << 1) | + * (((x) & 0x32323232U) << 2) | + * (((x) & 0x01010101U) << 5) | + * (((x) & 0xC0C0C0C0U) >> 5) | + * (((x) & 0x04040404U) >> 2)) + * + * x = SBOX_SWAP(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_PERMUTE_INV(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_PERMUTE_INV and SBOX_SWAP steps to be performed with one + * final permuatation. This reduces the number of shift operations. + */ +#define skinny128_inv_sbox(x) \ +do { \ + uint32_t y; \ + \ + /* Mix the bits */ \ + x = ~x; \ + y = (((x >> 1) & (x >> 3)) & 0x01010101U); \ + x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y; \ + y = (((x >> 6) & (x >> 1)) & 0x02020202U); \ + x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y; \ + y = (((x << 2) & (x << 1)) & 0x80808080U); \ + x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y; \ + y = (((x << 5) & (x << 1)) & 0x20202020U); \ + x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y; \ + x = ~x; \ + \ + /* Permutation generated by http://programming.sirrida.de/calcperm.php */ \ + /* The final permutation for each byte is [5 3 0 4 6 7 2 1] */ \ + x = ((x & 0x01010101U) << 2) | \ + ((x & 0x04040404U) << 4) | \ + ((x & 0x02020202U) << 6) | \ + ((x & 0x20202020U) >> 5) | \ + ((x & 0xC8C8C8C8U) >> 2) | \ + ((x & 0x10101010U) >> 1); \ +} while (0) + +/* Utilities for implementing SKINNY-64 */ + +#define skinny64_LFSR2(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x << 1) & 0xEEEEU) ^ (((_x >> 3) ^ (_x >> 2)) & 0x1111U); \ + } while (0) + +#define skinny64_LFSR3(x) \ + do { \ + uint16_t _x = (x); \ + (x) = ((_x >> 1) & 0x7777U) ^ ((_x ^ (_x << 3)) & 0x8888U); \ + } while (0) + +/* LFSR2 and LFSR3 are inverses of each other */ +#define skinny64_inv_LFSR2(x) skinny64_LFSR3(x) +#define skinny64_inv_LFSR3(x) skinny64_LFSR2(x) + +#define skinny64_permute_tk(tk) \ + do { \ + /* PT = [9, 15, 8, 13, 10, 14, 12, 11, 0, 1, 2, 3, 4, 5, 6, 7] */ \ + uint16_t row2 = tk[2]; \ + uint16_t row3 = tk[3]; \ + tk[2] = tk[0]; \ + tk[3] = tk[1]; \ + row3 = (row3 << 8) | (row3 >> 8); \ + tk[0] = ((row2 << 4) & 0xF000U) | \ + ((row2 >> 8) & 0x00F0U) | \ + ( row3 & 0x0F0FU); \ + tk[1] = ((row2 << 8) & 0xF000U) | \ + ((row3 >> 4) & 0x0F00U) | \ + ( row3 & 0x00F0U) | \ + ( row2 & 0x000FU); \ + } while (0) + +#define skinny64_inv_permute_tk(tk) \ + do { \ + /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ + uint16_t row0 = tk[0]; \ + uint16_t row1 = tk[1]; \ + tk[0] = tk[2]; \ + tk[1] = tk[3]; \ + tk[2] = ((row0 << 8) & 0xF000U) | \ + ((row0 >> 4) & 0x0F00U) | \ + ((row1 >> 8) & 0x00F0U) | \ + ( row1 & 0x000FU); \ + tk[3] = ((row1 << 8) & 0xF000U) | \ + ((row0 << 8) & 0x0F00U) | \ + ((row1 >> 4) & 0x00F0U) | \ + ((row0 >> 8) & 0x000FU); \ + } while (0) + +/* + * Apply the SKINNY-64 sbox. The original version from the + * specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT(x) + * ((((x) << 1) & 0xEEEEU) | (((x) >> 3) & 0x1111U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT(x); + * return SBOX_MIX(x); + * + * However, we can mix the bits in their original positions and then + * delay the SBOX_SHIFT steps to be performed with one final rotation. + * This reduces the number of required shift operations from 14 to 10. + * + * We can further reduce the number of NOT operations from 4 to 2 + * using the technique from https://github.com/kste/skinny_avx to + * convert NOR-XOR operations into AND-XOR operations by converting + * the S-box into its NOT-inverse. + */ +#define skinny64_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x >> 2) & (x << 1)) & 0x2222U) ^ x; \ + x = ~x; \ + x = ((x >> 1) & 0x7777U) | ((x << 3) & 0x8888U); \ +} while (0) + +/* + * Apply the inverse of the SKINNY-64 sbox. The original version + * from the specification is equivalent to: + * + * #define SBOX_MIX(x) + * (((~((((x) >> 1) | (x)) >> 2)) & 0x1111U) ^ (x)) + * #define SBOX_SHIFT_INV(x) + * ((((x) >> 1) & 0x7777U) | (((x) << 3) & 0x8888U)) + * + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * x = SBOX_MIX(x); + * x = SBOX_SHIFT_INV(x); + * return SBOX_MIX(x); + */ +#define skinny64_inv_sbox(x) \ +do { \ + x = ~x; \ + x = (((x >> 3) & (x >> 2)) & 0x1111U) ^ x; \ + x = (((x << 1) & (x >> 2)) & 0x2222U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x4444U) ^ x; \ + x = (((x << 1) & (x << 2)) & 0x8888U) ^ x; \ + x = ~x; \ + x = ((x << 1) & 0xEEEEU) | ((x >> 3) & 0x1111U); \ +} while (0) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-util.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.c b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.c new file mode 100644 index 0000000..2bb37e9 --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.c @@ -0,0 +1,803 @@ +/* + * 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-aead.h" +#include "internal-skinny128.h" +#include "internal-util.h" +#include + +aead_cipher_t const skinny_aead_m1_cipher = { + "SKINNY-AEAD-M1", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M1_NONCE_SIZE, + SKINNY_AEAD_M1_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m1_encrypt, + skinny_aead_m1_decrypt +}; + +aead_cipher_t const skinny_aead_m2_cipher = { + "SKINNY-AEAD-M2", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M2_NONCE_SIZE, + SKINNY_AEAD_M2_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m2_encrypt, + skinny_aead_m2_decrypt +}; + +aead_cipher_t const skinny_aead_m3_cipher = { + "SKINNY-AEAD-M3", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M3_NONCE_SIZE, + SKINNY_AEAD_M3_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m3_encrypt, + skinny_aead_m3_decrypt +}; + +aead_cipher_t const skinny_aead_m4_cipher = { + "SKINNY-AEAD-M4", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M4_NONCE_SIZE, + SKINNY_AEAD_M4_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m4_encrypt, + skinny_aead_m4_decrypt +}; + +aead_cipher_t const skinny_aead_m5_cipher = { + "SKINNY-AEAD-M5", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M5_NONCE_SIZE, + SKINNY_AEAD_M5_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m5_encrypt, + skinny_aead_m5_decrypt +}; + +aead_cipher_t const skinny_aead_m6_cipher = { + "SKINNY-AEAD-M6", + SKINNY_AEAD_KEY_SIZE, + SKINNY_AEAD_M6_NONCE_SIZE, + SKINNY_AEAD_M6_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + skinny_aead_m6_encrypt, + skinny_aead_m6_decrypt +}; + +/* Domain separator prefixes for all of the SKINNY-AEAD family members */ +#define DOMAIN_SEP_M1 0x00 +#define DOMAIN_SEP_M2 0x10 +#define DOMAIN_SEP_M3 0x08 +#define DOMAIN_SEP_M4 0x18 +#define DOMAIN_SEP_M5 0x10 +#define DOMAIN_SEP_M6 0x18 + +/** + * \brief Initialize the key and nonce for SKINNY-128-384 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_384_init + (skinny_128_384_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memcpy(k, nonce, nonce_len); + memset(k + nonce_len, 0, 16 - nonce_len); + memcpy(k + 16, key, 16); + skinny_128_384_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_384_set_domain(ks,d) ((ks)->TK1[15] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-384. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 64-bit LFSR value. + */ +#define skinny_aead_128_384_set_lfsr(ks,lfsr) le_store_word64((ks)->TK1, (lfsr)) + +/** + * \brief Updates the LFSR value for SKINNY-128-384. + * + * \param lfsr 64-bit LFSR value to be updated. + */ +#define skinny_aead_128_384_update_lfsr(lfsr) \ + do { \ + uint8_t feedback = ((lfsr) & (1ULL << 63)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) | feedback; \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_384_authenticate + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + skinny_aead_128_384_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_384_encrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-384 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_384_decrypt + (skinny_128_384_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint64_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_384_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_128_384_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_384_update_lfsr(lfsr); + } + skinny_aead_128_384_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_384_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_384_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_384_update_lfsr(lfsr); + skinny_aead_128_384_set_lfsr(ks, lfsr); + skinny_aead_128_384_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_384_set_domain(ks, prefix | 4); + } + skinny_128_384_encrypt(ks, sum, sum); +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M1, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M1_TAG_SIZE); + return 0; +} + +int skinny_aead_m1_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M1_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M1_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M1_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M1, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M1, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M1_TAG_SIZE); +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M2, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M2_TAG_SIZE); + return 0; +} + +int skinny_aead_m2_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M2_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M2_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M2_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M2, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M2, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M2_TAG_SIZE); +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M3, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M3_TAG_SIZE); + return 0; +} + +int skinny_aead_m3_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M3_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M3_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M3_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M3, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M3, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M3_TAG_SIZE); +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_384_encrypt(&ks, DOMAIN_SEP_M4, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M4_TAG_SIZE); + return 0; +} + +int skinny_aead_m4_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) +{ + skinny_128_384_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M4_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M4_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_384_init(&ks, k, npub, SKINNY_AEAD_M4_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_384_decrypt(&ks, DOMAIN_SEP_M4, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_384_authenticate(&ks, DOMAIN_SEP_M4, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M4_TAG_SIZE); +} + +/** + * \brief Initialize the key and nonce for SKINNY-128-256 based AEAD schemes. + * + * \param ks The key schedule to initialize. + * \param key Points to the 16 bytes of the key. + * \param nonce Points to the nonce. + * \param nonce_len Length of the nonce in bytes. + */ +static void skinny_aead_128_256_init + (skinny_128_256_key_schedule_t *ks, const unsigned char *key, + const unsigned char *nonce, unsigned nonce_len) +{ + unsigned char k[32]; + memset(k, 0, 16 - nonce_len); + memcpy(k + 16 - nonce_len, nonce, nonce_len); + memcpy(k + 16, key, 16); + skinny_128_256_init(ks, k, 32); +} + +/** + * \brief Set the domain separation value in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param d Domain separation value to write into the tweak. + */ +#define skinny_aead_128_256_set_domain(ks,d) ((ks)->TK1[3] = (d)) + +/** + * \brief Sets the LFSR field in the tweak for SKINNY-128-256. + * + * \param ks Key schedule for the block cipher. + * \param lfsr 24-bit LFSR value. + */ +#define skinny_aead_128_256_set_lfsr(ks,lfsr) \ + do { \ + (ks)->TK1[0] = (uint8_t)(lfsr); \ + (ks)->TK1[1] = (uint8_t)((lfsr) >> 8); \ + (ks)->TK1[2] = (uint8_t)((lfsr) >> 16); \ + } while (0) + +/** + * \brief Updates the LFSR value for SKINNY-128-256. + * + * \param lfsr 24-bit LFSR value to be updated. + */ +#define skinny_aead_128_256_update_lfsr(lfsr) \ + do { \ + uint32_t feedback = ((lfsr) & (((uint32_t)1) << 23)) ? 0x1B : 0x00; \ + (lfsr) = ((lfsr) << 1) ^ (feedback); \ + } while (0) + +/** + * \brief Authenticates the associated data for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param tag Final tag to XOR the authentication checksum into. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void skinny_aead_128_256_authenticate + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char tag[SKINNY_128_BLOCK_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + skinny_aead_128_256_set_domain(ks, prefix | 2); + while (adlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_encrypt(ks, block, ad); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + ad += SKINNY_128_BLOCK_SIZE; + adlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 3); + memcpy(block, ad, temp); + block[temp] = 0x80; + memset(block + temp + 1, 0, SKINNY_128_BLOCK_SIZE - temp - 1); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block(tag, block, SKINNY_128_BLOCK_SIZE); + } +} + +/** + * \brief Encrypts the plaintext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param c Points to the buffer to receive the ciphertext. + * \param m Points to the plaintext buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void skinny_aead_128_256_encrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, c, m); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(c, block, m, temp); + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +/** + * \brief Decrypts the ciphertext for a SKINNY-128-256 based AEAD. + * + * \param ks The key schedule to use. + * \param prefix Domain separation prefix for the family member. + * \param sum Authenticated checksum over the plaintext. + * \param m Points to the buffer to receive the plaintext. + * \param c Points to the ciphertext buffer. + * \param mlen Number of bytes of ciphertext to be decrypted. + */ +static void skinny_aead_128_256_decrypt + (skinny_128_256_key_schedule_t *ks, unsigned char prefix, + unsigned char sum[SKINNY_128_BLOCK_SIZE], unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + unsigned char block[SKINNY_128_BLOCK_SIZE]; + uint32_t lfsr = 1; + memset(sum, 0, SKINNY_128_BLOCK_SIZE); + skinny_aead_128_256_set_domain(ks, prefix | 0); + while (mlen >= SKINNY_128_BLOCK_SIZE) { + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_128_256_decrypt(ks, m, c); + lw_xor_block(sum, m, SKINNY_128_BLOCK_SIZE); + c += SKINNY_128_BLOCK_SIZE; + m += SKINNY_128_BLOCK_SIZE; + mlen -= SKINNY_128_BLOCK_SIZE; + skinny_aead_128_256_update_lfsr(lfsr); + } + skinny_aead_128_256_set_lfsr(ks, lfsr); + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + skinny_aead_128_256_set_domain(ks, prefix | 1); + memset(block, 0, SKINNY_128_BLOCK_SIZE); + skinny_128_256_encrypt(ks, block, block); + lw_xor_block_2_src(m, block, c, temp); + lw_xor_block(sum, m, temp); + sum[temp] ^= 0x80; + skinny_aead_128_256_update_lfsr(lfsr); + skinny_aead_128_256_set_lfsr(ks, lfsr); + skinny_aead_128_256_set_domain(ks, prefix | 5); + } else { + skinny_aead_128_256_set_domain(ks, prefix | 4); + } + skinny_128_256_encrypt(ks, sum, sum); +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M5, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M5_TAG_SIZE); + return 0; +} + +int skinny_aead_m5_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M5_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M5_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M5_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M5, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M5, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M5_TAG_SIZE); +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Encrypt to plaintext to produce the ciphertext */ + skinny_aead_128_256_encrypt(&ks, DOMAIN_SEP_M6, sum, c, m, mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Generate the authentication tag */ + memcpy(c + mlen, sum, SKINNY_AEAD_M6_TAG_SIZE); + return 0; +} + +int skinny_aead_m6_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) +{ + skinny_128_256_key_schedule_t ks; + unsigned char sum[SKINNY_128_BLOCK_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SKINNY_AEAD_M6_TAG_SIZE) + return -1; + *mlen = clen - SKINNY_AEAD_M6_TAG_SIZE; + + /* Set up the key schedule with the key and the nonce */ + skinny_aead_128_256_init(&ks, k, npub, SKINNY_AEAD_M6_NONCE_SIZE); + + /* Decrypt to ciphertext to produce the plaintext */ + skinny_aead_128_256_decrypt(&ks, DOMAIN_SEP_M6, sum, m, c, *mlen); + + /* Process the associated data */ + skinny_aead_128_256_authenticate(&ks, DOMAIN_SEP_M6, sum, ad, adlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, sum, c + *mlen, SKINNY_AEAD_M6_TAG_SIZE); +} diff --git a/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.h b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.h new file mode 100644 index 0000000..c6b54fb --- /dev/null +++ b/skinny/Implementations/crypto_aead/skinnyaeadtk39664v1/rhys/skinny-aead.h @@ -0,0 +1,518 @@ +/* + * 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_AEAD_H +#define LWCRYPTO_SKINNY_AEAD_H + +#include "aead-common.h" + +/** + * \file skinny-aead.h + * \brief Authenticated encryption based on the SKINNY block cipher. + * + * SKINNY-AEAD is a family of authenticated encryption algorithms + * that are built around the SKINNY tweakable block cipher. There + * are six members in the family: + * + * \li SKINNY-AEAD-M1 has a 128-bit key, a 128-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. This is the + * primary member of the family. + * \li SKINNY-AEAD-M2 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M3 has a 128-bit key, a 128-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M4 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-384 tweakable block cipher. + * \li SKINNY-AEAD-M5 has a 128-bit key, a 96-bit nonce, and a 128-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * \li SKINNY-AEAD-M6 has a 128-bit key, a 96-bit nonce, and a 64-bit tag, + * based around the SKINNY-128-256 tweakable block cipher. + * + * The SKINNY-AEAD family also 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 key for all SKINNY-AEAD family members. + */ +#define SKINNY_AEAD_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M1. + */ +#define SKINNY_AEAD_M1_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M2. + */ +#define SKINNY_AEAD_M2_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M3. + */ +#define SKINNY_AEAD_M3_NONCE_SIZE 16 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M4. + */ +#define SKINNY_AEAD_M4_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M5. + */ +#define SKINNY_AEAD_M5_NONCE_SIZE 12 + +/** + * \brief Size of the authentication tag for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_TAG_SIZE 8 + +/** + * \brief Size of the nonce for SKINNY-AEAD-M6. + */ +#define SKINNY_AEAD_M6_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the SKINNY-AEAD-M1 cipher. + */ +extern aead_cipher_t const skinny_aead_m1_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M2 cipher. + */ +extern aead_cipher_t const skinny_aead_m2_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M3 cipher. + */ +extern aead_cipher_t const skinny_aead_m3_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M4 cipher. + */ +extern aead_cipher_t const skinny_aead_m4_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M5 cipher. + */ +extern aead_cipher_t const skinny_aead_m5_cipher; + +/** + * \brief Meta-information block for the SKINNY-AEAD-M6 cipher. + */ +extern aead_cipher_t const skinny_aead_m6_cipher; + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m1_decrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M1. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m1_encrypt() + */ +int skinny_aead_m1_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m2_decrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M2. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m2_encrypt() + */ +int skinny_aead_m2_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m3_decrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M3. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m3_encrypt() + */ +int skinny_aead_m3_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m4_decrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M4. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m4_encrypt() + */ +int skinny_aead_m4_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m5_decrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M5. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m5_encrypt() + */ +int skinny_aead_m5_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); + +/** + * \brief Encrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa skinny_aead_m6_decrypt() + */ +int skinny_aead_m6_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); + +/** + * \brief Decrypts and authenticates a packet with SKINNY-AEAD-M6. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa skinny_aead_m6_encrypt() + */ +int skinny_aead_m6_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.c b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.h b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/api.h b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/encrypt.c b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/encrypt.c new file mode 100644 index 0000000..a56e57a --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sparkle.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 schwaemm_128_128_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 schwaemm_128_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.c new file mode 100644 index 0000000..822af50 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.c @@ -0,0 +1,366 @@ +/* + * 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 "internal-sparkle.h" + +/* The 8 basic round constants from the specification */ +#define RC_0 0xB7E15162 +#define RC_1 0xBF715880 +#define RC_2 0x38B4DA56 +#define RC_3 0x324E7738 +#define RC_4 0xBB1185EB +#define RC_5 0x4F7C7B57 +#define RC_6 0xCFBFA1C8 +#define RC_7 0xC2B3293D + +/* Round constants for all SPARKLE steps; maximum of 12 for SPARKLE-512 */ +static uint32_t const sparkle_rc[12] = { + RC_0, RC_1, RC_2, RC_3, RC_4, RC_5, RC_6, RC_7, + RC_0, RC_1, RC_2, RC_3 +}; + +/** + * \brief Alzette block cipher that implements the ARXbox layer of the + * SPARKLE permutation. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param k 32-bit round key. + */ +#define alzette(x, y, k) \ + do { \ + (x) += leftRotate1((y)); \ + (y) ^= leftRotate8((x)); \ + (x) ^= (k); \ + (x) += leftRotate15((y)); \ + (y) ^= leftRotate15((x)); \ + (x) ^= (k); \ + (x) += (y); \ + (y) ^= leftRotate1((x)); \ + (x) ^= (k); \ + (x) += leftRotate8((y)); \ + (y) ^= leftRotate16((x)); \ + (x) ^= (k); \ + } while (0) + +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-256 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + + /* Linear layer */ + tx = x0 ^ x1; + ty = y0 ^ y1; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x3 ^ x1 ^ ty; + x3 = x1; + y0 = y3 ^ y1 ^ tx; + y3 = y1; + x1 = x2 ^ tw ^ ty; + x2 = tw; + y1 = y2 ^ tz ^ tx; + y2 = tz; + } + + /* Write the local variables back to the SPARKLE-256 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); +#endif +} + +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t y0, y1, y2, y3, y4, y5; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-384 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2; + ty = y0 ^ y1 ^ y2; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x4 ^ x1 ^ ty; + x4 = x1; + y0 = y4 ^ y1 ^ tx; + y4 = y1; + x1 = x5 ^ x2 ^ ty; + x5 = x2; + y1 = y5 ^ y2 ^ tx; + y5 = y2; + x2 = x3 ^ tw ^ ty; + x3 = tw; + y2 = y3 ^ tz ^ tx; + y3 = tz; + } + + /* Write the local variables back to the SPARKLE-384 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); +#endif +} + +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y0, y1, y2, y3, y4, y5, y6, y7; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-512 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; + x6 = s[12]; + y6 = s[13]; + x7 = s[14]; + y7 = s[15]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); + x6 = le_load_word32((const uint8_t *)&(s[12])); + y6 = le_load_word32((const uint8_t *)&(s[13])); + x7 = le_load_word32((const uint8_t *)&(s[14])); + y7 = le_load_word32((const uint8_t *)&(s[15])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + alzette(x6, y6, RC_6); + alzette(x7, y7, RC_7); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2 ^ x3; + ty = y0 ^ y1 ^ y2 ^ y3; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x5 ^ x1 ^ ty; + x5 = x1; + y0 = y5 ^ y1 ^ tx; + y5 = y1; + x1 = x6 ^ x2 ^ ty; + x6 = x2; + y1 = y6 ^ y2 ^ tx; + y6 = y2; + x2 = x7 ^ x3 ^ ty; + x7 = x3; + y2 = y7 ^ y3 ^ tx; + y7 = y3; + x3 = x4 ^ tw ^ ty; + x4 = tw; + y3 = y4 ^ tz ^ tx; + y4 = tz; + } + + /* Write the local variables back to the SPARKLE-512 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; + s[12] = x6; + s[13] = y6; + s[14] = x7; + s[15] = y7; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); + le_store_word32((uint8_t *)&(s[12]), x6); + le_store_word32((uint8_t *)&(s[13]), y6); + le_store_word32((uint8_t *)&(s[14]), x7); + le_store_word32((uint8_t *)&(s[15]), y7); +#endif +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.h new file mode 100644 index 0000000..fbdabc1 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-sparkle.h @@ -0,0 +1,82 @@ +/* + * 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_SPARKLE_H +#define LW_INTERNAL_SPARKLE_H + +#include "internal-util.h" + +/** + * \file internal-sparkle.h + * \brief Internal implementation of the SPARKLE permutation. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for SPARKLE-256. + */ +#define SPARKLE_256_STATE_SIZE 8 + +/** + * \brief Size of the state for SPARKLE-384. + */ +#define SPARKLE_384_STATE_SIZE 12 + +/** + * \brief Size of the state for SPARKLE-512. + */ +#define SPARKLE_512_STATE_SIZE 16 + +/** + * \brief Performs the SPARKLE-256 permutation. + * + * \param s The words of the SPARKLE-256 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 10. + */ +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-384 permutation. + * + * \param s The words of the SPARKLE-384 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 11. + */ +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-512 permutation. + * + * \param s The words of the SPARKLE-512 state in little-endian byte order. + * \param steps The number of steps to perform, 8 or 12. + */ +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-util.h b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.c new file mode 100644 index 0000000..b357de6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.c @@ -0,0 +1,1123 @@ +/* + * 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 "sparkle.h" +#include "internal-sparkle.h" +#include + +aead_cipher_t const schwaemm_256_128_cipher = { + "Schwaemm256-128", + SCHWAEMM_256_128_KEY_SIZE, + SCHWAEMM_256_128_NONCE_SIZE, + SCHWAEMM_256_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_128_aead_encrypt, + schwaemm_256_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_192_192_cipher = { + "Schwaemm192-192", + SCHWAEMM_192_192_KEY_SIZE, + SCHWAEMM_192_192_NONCE_SIZE, + SCHWAEMM_192_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_192_192_aead_encrypt, + schwaemm_192_192_aead_decrypt +}; + +aead_cipher_t const schwaemm_128_128_cipher = { + "Schwaemm128-128", + SCHWAEMM_128_128_KEY_SIZE, + SCHWAEMM_128_128_NONCE_SIZE, + SCHWAEMM_128_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_128_128_aead_encrypt, + schwaemm_128_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_256_256_cipher = { + "Schwaemm256-256", + SCHWAEMM_256_256_KEY_SIZE, + SCHWAEMM_256_256_NONCE_SIZE, + SCHWAEMM_256_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_256_aead_encrypt, + schwaemm_256_256_aead_decrypt +}; + +aead_hash_algorithm_t const esch_256_hash_algorithm = { + "Esch256", + sizeof(esch_256_hash_state_t), + ESCH_256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_256_hash, + (aead_hash_init_t)esch_256_hash_init, + (aead_hash_update_t)esch_256_hash_update, + (aead_hash_finalize_t)esch_256_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +aead_hash_algorithm_t const esch_384_hash_algorithm = { + "Esch384", + sizeof(esch_384_hash_state_t), + ESCH_384_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_384_hash, + (aead_hash_init_t)esch_384_hash_init, + (aead_hash_update_t)esch_384_hash_update, + (aead_hash_finalize_t)esch_384_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +/** + * \def DOMAIN(value) + * \brief Build a domain separation value as a 32-bit word. + * + * \param value The base value. + * \return The domain separation value as a 32-bit word. + */ +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define DOMAIN(value) (((uint32_t)(value)) << 24) +#else +#define DOMAIN(value) (value) +#endif + +/** + * \brief Rate at which bytes are processed by Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RIGHT(s) \ + (SCHWAEMM_256_128_LEFT(s) + SCHWAEMM_256_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[8]; \ + s[5] ^= t1 ^ s[9]; \ + s[6] ^= t2 ^ s[10]; \ + s[7] ^= t3 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_128_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_256_128_RATE; + adlen -= SCHWAEMM_256_128_RATE; + } + if (adlen == SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_256_128_RATE); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + mlen -= SCHWAEMM_256_128_RATE; + } + if (mlen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + memcpy(c, block, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return 0; +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + clen -= SCHWAEMM_256_128_RATE; + } + if (clen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_128_RIGHT(s), c, SCHWAEMM_256_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RATE 24 + +/** + * \brief Pointer to the left of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RIGHT(s) \ + (SCHWAEMM_192_192_LEFT(s) + SCHWAEMM_192_192_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_192_192_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[3] ^ s[6]; \ + s[1] = s[4] ^ s[7]; \ + s[2] = s[5] ^ s[8]; \ + s[3] ^= t0 ^ s[9]; \ + s[4] ^= t1 ^ s[10]; \ + s[5] ^= t2 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_192_192_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_192_192_RATE; + adlen -= SCHWAEMM_192_192_RATE; + } + if (adlen == SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x09); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_192_192_rho(s, 0x08); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_192_192_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_192_192_RATE); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + mlen -= SCHWAEMM_192_192_RATE; + } + if (mlen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + memcpy(c, block, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return 0; +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_192_192_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_192_192_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + clen -= SCHWAEMM_192_192_RATE; + } + if (clen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_192_192_RIGHT(s), c, SCHWAEMM_192_192_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RATE 16 + +/** + * \brief Pointer to the left of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RIGHT(s) \ + (SCHWAEMM_128_128_LEFT(s) + SCHWAEMM_128_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_128_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[0] = s[2] ^ s[4]; \ + s[1] = s[3] ^ s[5]; \ + s[2] ^= t0 ^ s[6]; \ + s[3] ^= t1 ^ s[7]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_128_128_authenticate + (uint32_t s[SPARKLE_256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + ad += SCHWAEMM_128_128_RATE; + adlen -= SCHWAEMM_128_128_RATE; + } + if (adlen == SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_128_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + uint8_t block[SCHWAEMM_128_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + memcpy(c, block, SCHWAEMM_128_128_RATE); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + mlen -= SCHWAEMM_128_128_RATE; + } + if (mlen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + memcpy(c, block, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_256(s, 10); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return 0; +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_128_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_128_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + clen -= SCHWAEMM_128_128_RATE; + } + if (clen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_128_128_RIGHT(s), c, SCHWAEMM_128_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RIGHT(s) \ + (SCHWAEMM_256_256_LEFT(s) + SCHWAEMM_256_256_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_256_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[15] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[12]; \ + s[5] ^= t1 ^ s[13]; \ + s[6] ^= t2 ^ s[14]; \ + s[7] ^= t3 ^ s[15]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_256_authenticate + (uint32_t s[SPARKLE_512_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + ad += SCHWAEMM_256_256_RATE; + adlen -= SCHWAEMM_256_256_RATE; + } + if (adlen == SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x11); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_256_rho(s, 0x10); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_256_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + memcpy(c, block, SCHWAEMM_256_256_RATE); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + mlen -= SCHWAEMM_256_256_RATE; + } + if (mlen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + memcpy(c, block, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_512(s, 12); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return 0; +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_256_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_256_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + clen -= SCHWAEMM_256_256_RATE; + } + if (clen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_256_RIGHT(s), c, SCHWAEMM_256_256_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Esch256. + */ +#define ESCH_256_RATE 16 + +/** + * \brief Perform the M3 step for Esch256 to mix the input with the state. + * + * \param s SPARKLE-384 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_256_m3(s, block, domain) \ + do { \ + uint32_t tx = (block)[0] ^ (block)[2]; \ + uint32_t ty = (block)[1] ^ (block)[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= (block)[0] ^ ty; \ + s[1] ^= (block)[1] ^ tx; \ + s[2] ^= (block)[2] ^ ty; \ + s[3] ^= (block)[3] ^ tx; \ + if ((domain) != 0) \ + s[5] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + } while (0) + +/** @cond esch_256 */ + +/** + * \brief Word-based state for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_384_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_256_hash_state_wt; + +/** @endcond */ + +int esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x00); + sparkle_384(s, 7); + in += ESCH_256_RATE; + inlen -= ESCH_256_RATE; + } + if (inlen == ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(s, block, 0x01); + } + sparkle_384(s, 11); + memcpy(out, s, ESCH_256_RATE); + sparkle_384(s, 7); + memcpy(out + ESCH_256_RATE, s, ESCH_256_RATE); + return 0; +} + +void esch_256_hash_init(esch_256_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_256_hash_state_t)); +} + +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x00); + sparkle_384(st->s.state, 7); + st->s.count = 0; + } + temp = ESCH_256_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(st->s.state, st->s.block, 0x01); + } + sparkle_384(st->s.state, 11); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_256_RATE); + sparkle_384(st->s.state, 7); + memcpy(out + ESCH_256_RATE, st->s.state, ESCH_256_RATE); +} + +/** + * \brief Rate at which bytes are processed by Esch384. + */ +#define ESCH_384_RATE 16 + +/** + * \brief Perform the M4 step for Esch384 to mix the input with the state. + * + * \param s SPARKLE-512 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_384_m4(s, block, domain) \ + do { \ + uint32_t tx = block[0] ^ block[2]; \ + uint32_t ty = block[1] ^ block[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= block[0] ^ ty; \ + s[1] ^= block[1] ^ tx; \ + s[2] ^= block[2] ^ ty; \ + s[3] ^= block[3] ^ tx; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + s[6] ^= ty; \ + s[7] ^= tx; \ + } while (0) + +/** @cond esch_384 */ + +/** + * \brief Word-based state for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_512_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_384_hash_state_wt; + +/** @endcond */ + +int esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x00); + sparkle_512(s, 8); + in += ESCH_384_RATE; + inlen -= ESCH_384_RATE; + } + if (inlen == ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(s, block, 0x01); + } + sparkle_512(s, 12); + memcpy(out, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE * 2, s, ESCH_384_RATE); + return 0; +} + +void esch_384_hash_init(esch_384_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_384_hash_state_t)); +} + +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x00); + sparkle_512(st->s.state, 8); + st->s.count = 0; + } + temp = ESCH_384_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(st->s.state, st->s.block, 0x01); + } + sparkle_512(st->s.state, 12); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE * 2, st->s.state, ESCH_384_RATE); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.h new file mode 100644 index 0000000..dd0999e --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm128128v1/rhys/sparkle.h @@ -0,0 +1,515 @@ +/* + * 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_SPARKLE_H +#define LWCRYPTO_SPARKLE_H + +#include "aead-common.h" + +/** + * \file sparkle.h + * \brief Encryption and hash algorithms based on the SPARKLE permutation. + * + * SPARKLE is a family of encryption and hash algorithms that are based + * around the SPARKLE permutation. There are three versions of the + * permutation with 256-bit, 384-bit, and 512-bit state sizes. + * The algorithms in the family are: + * + * \li Schwaemm256-128 with a 128-bit key, a 256-bit nonce, and a 128-bit tag. + * This is the primary encryption algorithm in the family. + * \li Schwaemm192-192 with a 192-bit key, a 192-bit nonce, and a 192-bit tag. + * \li Schwaemm128-128 with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * \li Schwaemm256-256 with a 256-bit key, a 256-bit nonce, and a 256-bit tag. + * \li Esch256 hash algorithm with a 256-bit digest output. This is the + * primary hash algorithm in the family. + * \li Esch384 hash algorithm with a 384-bit digest output. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_NONCE_SIZE 32 + +/** + * \brief Size of the key for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash output for Esch256. + */ +#define ESCH_256_HASH_SIZE 32 + +/** + * \brief Size of the hash output for Esch384. + */ +#define ESCH_384_HASH_SIZE 48 + +/** + * \brief Meta-information block for the Schwaemm256-128 cipher. + */ +extern aead_cipher_t const schwaemm_256_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm192-192 cipher. + */ +extern aead_cipher_t const schwaemm_192_192_cipher; + +/** + * \brief Meta-information block for the Schwaemm128-128 cipher. + */ +extern aead_cipher_t const schwaemm_128_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm256-256 cipher. + */ +extern aead_cipher_t const schwaemm_256_256_cipher; + +/** + * \brief Meta-information block for the Esch256 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_256_hash_algorithm; + +/** + * \brief Meta-information block for the Esch384 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_384_hash_algorithm; + +/** + * \brief State information for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_256_hash_state_t; + +/** + * \brief State information for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[64]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_384_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_128_aead_decrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_128_aead_encrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm192-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 24 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_192_192_aead_decrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm192-192. + * + * \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 - not used by this algorithm. + * \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 24 byte 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 which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa schwaemm_192_192_aead_encrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm128-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_128_128_aead_decrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm128-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_128_128_aead_encrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_256_aead_decrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_256_aead_encrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Hashes a block of input data with Esch256 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_256_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 esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch256 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_256_hash_update(), esch_256_hash_finalize(), esch_256_hash() + */ +void esch_256_hash_init(esch_256_hash_state_t *state); + +/** + * \brief Updates an Esch256 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. + * + * \sa esch_256_hash_init(), esch_256_hash_finalize() + */ +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch256 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa esch_256_hash_init(), esch_256_hash_update() + */ +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with Esch384 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_384_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 esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch384 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_384_hash_update(), esch_384_hash_finalize(), esch_384_hash() + */ +void esch_384_hash_init(esch_384_hash_state_t *state); + +/** + * \brief Updates an Esch384 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. + * + * \sa esch_384_hash_init(), esch_384_hash_finalize() + */ +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch384 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 48-byte hash value. + * + * \sa esch_384_hash_init(), esch_384_hash_update() + */ +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.c b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.h b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/api.h b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/api.h new file mode 100644 index 0000000..c340ebc --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 24 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 24 +#define CRYPTO_ABYTES 24 +#define CRYPTO_NOOVERLAP 1 diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/encrypt.c b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/encrypt.c new file mode 100644 index 0000000..43a4aac --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sparkle.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 schwaemm_192_192_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 schwaemm_192_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.c new file mode 100644 index 0000000..822af50 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.c @@ -0,0 +1,366 @@ +/* + * 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 "internal-sparkle.h" + +/* The 8 basic round constants from the specification */ +#define RC_0 0xB7E15162 +#define RC_1 0xBF715880 +#define RC_2 0x38B4DA56 +#define RC_3 0x324E7738 +#define RC_4 0xBB1185EB +#define RC_5 0x4F7C7B57 +#define RC_6 0xCFBFA1C8 +#define RC_7 0xC2B3293D + +/* Round constants for all SPARKLE steps; maximum of 12 for SPARKLE-512 */ +static uint32_t const sparkle_rc[12] = { + RC_0, RC_1, RC_2, RC_3, RC_4, RC_5, RC_6, RC_7, + RC_0, RC_1, RC_2, RC_3 +}; + +/** + * \brief Alzette block cipher that implements the ARXbox layer of the + * SPARKLE permutation. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param k 32-bit round key. + */ +#define alzette(x, y, k) \ + do { \ + (x) += leftRotate1((y)); \ + (y) ^= leftRotate8((x)); \ + (x) ^= (k); \ + (x) += leftRotate15((y)); \ + (y) ^= leftRotate15((x)); \ + (x) ^= (k); \ + (x) += (y); \ + (y) ^= leftRotate1((x)); \ + (x) ^= (k); \ + (x) += leftRotate8((y)); \ + (y) ^= leftRotate16((x)); \ + (x) ^= (k); \ + } while (0) + +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-256 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + + /* Linear layer */ + tx = x0 ^ x1; + ty = y0 ^ y1; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x3 ^ x1 ^ ty; + x3 = x1; + y0 = y3 ^ y1 ^ tx; + y3 = y1; + x1 = x2 ^ tw ^ ty; + x2 = tw; + y1 = y2 ^ tz ^ tx; + y2 = tz; + } + + /* Write the local variables back to the SPARKLE-256 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); +#endif +} + +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t y0, y1, y2, y3, y4, y5; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-384 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2; + ty = y0 ^ y1 ^ y2; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x4 ^ x1 ^ ty; + x4 = x1; + y0 = y4 ^ y1 ^ tx; + y4 = y1; + x1 = x5 ^ x2 ^ ty; + x5 = x2; + y1 = y5 ^ y2 ^ tx; + y5 = y2; + x2 = x3 ^ tw ^ ty; + x3 = tw; + y2 = y3 ^ tz ^ tx; + y3 = tz; + } + + /* Write the local variables back to the SPARKLE-384 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); +#endif +} + +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y0, y1, y2, y3, y4, y5, y6, y7; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-512 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; + x6 = s[12]; + y6 = s[13]; + x7 = s[14]; + y7 = s[15]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); + x6 = le_load_word32((const uint8_t *)&(s[12])); + y6 = le_load_word32((const uint8_t *)&(s[13])); + x7 = le_load_word32((const uint8_t *)&(s[14])); + y7 = le_load_word32((const uint8_t *)&(s[15])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + alzette(x6, y6, RC_6); + alzette(x7, y7, RC_7); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2 ^ x3; + ty = y0 ^ y1 ^ y2 ^ y3; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x5 ^ x1 ^ ty; + x5 = x1; + y0 = y5 ^ y1 ^ tx; + y5 = y1; + x1 = x6 ^ x2 ^ ty; + x6 = x2; + y1 = y6 ^ y2 ^ tx; + y6 = y2; + x2 = x7 ^ x3 ^ ty; + x7 = x3; + y2 = y7 ^ y3 ^ tx; + y7 = y3; + x3 = x4 ^ tw ^ ty; + x4 = tw; + y3 = y4 ^ tz ^ tx; + y4 = tz; + } + + /* Write the local variables back to the SPARKLE-512 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; + s[12] = x6; + s[13] = y6; + s[14] = x7; + s[15] = y7; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); + le_store_word32((uint8_t *)&(s[12]), x6); + le_store_word32((uint8_t *)&(s[13]), y6); + le_store_word32((uint8_t *)&(s[14]), x7); + le_store_word32((uint8_t *)&(s[15]), y7); +#endif +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.h new file mode 100644 index 0000000..fbdabc1 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-sparkle.h @@ -0,0 +1,82 @@ +/* + * 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_SPARKLE_H +#define LW_INTERNAL_SPARKLE_H + +#include "internal-util.h" + +/** + * \file internal-sparkle.h + * \brief Internal implementation of the SPARKLE permutation. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for SPARKLE-256. + */ +#define SPARKLE_256_STATE_SIZE 8 + +/** + * \brief Size of the state for SPARKLE-384. + */ +#define SPARKLE_384_STATE_SIZE 12 + +/** + * \brief Size of the state for SPARKLE-512. + */ +#define SPARKLE_512_STATE_SIZE 16 + +/** + * \brief Performs the SPARKLE-256 permutation. + * + * \param s The words of the SPARKLE-256 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 10. + */ +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-384 permutation. + * + * \param s The words of the SPARKLE-384 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 11. + */ +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-512 permutation. + * + * \param s The words of the SPARKLE-512 state in little-endian byte order. + * \param steps The number of steps to perform, 8 or 12. + */ +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-util.h b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.c new file mode 100644 index 0000000..b357de6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.c @@ -0,0 +1,1123 @@ +/* + * 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 "sparkle.h" +#include "internal-sparkle.h" +#include + +aead_cipher_t const schwaemm_256_128_cipher = { + "Schwaemm256-128", + SCHWAEMM_256_128_KEY_SIZE, + SCHWAEMM_256_128_NONCE_SIZE, + SCHWAEMM_256_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_128_aead_encrypt, + schwaemm_256_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_192_192_cipher = { + "Schwaemm192-192", + SCHWAEMM_192_192_KEY_SIZE, + SCHWAEMM_192_192_NONCE_SIZE, + SCHWAEMM_192_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_192_192_aead_encrypt, + schwaemm_192_192_aead_decrypt +}; + +aead_cipher_t const schwaemm_128_128_cipher = { + "Schwaemm128-128", + SCHWAEMM_128_128_KEY_SIZE, + SCHWAEMM_128_128_NONCE_SIZE, + SCHWAEMM_128_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_128_128_aead_encrypt, + schwaemm_128_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_256_256_cipher = { + "Schwaemm256-256", + SCHWAEMM_256_256_KEY_SIZE, + SCHWAEMM_256_256_NONCE_SIZE, + SCHWAEMM_256_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_256_aead_encrypt, + schwaemm_256_256_aead_decrypt +}; + +aead_hash_algorithm_t const esch_256_hash_algorithm = { + "Esch256", + sizeof(esch_256_hash_state_t), + ESCH_256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_256_hash, + (aead_hash_init_t)esch_256_hash_init, + (aead_hash_update_t)esch_256_hash_update, + (aead_hash_finalize_t)esch_256_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +aead_hash_algorithm_t const esch_384_hash_algorithm = { + "Esch384", + sizeof(esch_384_hash_state_t), + ESCH_384_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_384_hash, + (aead_hash_init_t)esch_384_hash_init, + (aead_hash_update_t)esch_384_hash_update, + (aead_hash_finalize_t)esch_384_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +/** + * \def DOMAIN(value) + * \brief Build a domain separation value as a 32-bit word. + * + * \param value The base value. + * \return The domain separation value as a 32-bit word. + */ +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define DOMAIN(value) (((uint32_t)(value)) << 24) +#else +#define DOMAIN(value) (value) +#endif + +/** + * \brief Rate at which bytes are processed by Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RIGHT(s) \ + (SCHWAEMM_256_128_LEFT(s) + SCHWAEMM_256_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[8]; \ + s[5] ^= t1 ^ s[9]; \ + s[6] ^= t2 ^ s[10]; \ + s[7] ^= t3 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_128_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_256_128_RATE; + adlen -= SCHWAEMM_256_128_RATE; + } + if (adlen == SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_256_128_RATE); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + mlen -= SCHWAEMM_256_128_RATE; + } + if (mlen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + memcpy(c, block, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return 0; +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + clen -= SCHWAEMM_256_128_RATE; + } + if (clen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_128_RIGHT(s), c, SCHWAEMM_256_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RATE 24 + +/** + * \brief Pointer to the left of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RIGHT(s) \ + (SCHWAEMM_192_192_LEFT(s) + SCHWAEMM_192_192_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_192_192_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[3] ^ s[6]; \ + s[1] = s[4] ^ s[7]; \ + s[2] = s[5] ^ s[8]; \ + s[3] ^= t0 ^ s[9]; \ + s[4] ^= t1 ^ s[10]; \ + s[5] ^= t2 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_192_192_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_192_192_RATE; + adlen -= SCHWAEMM_192_192_RATE; + } + if (adlen == SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x09); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_192_192_rho(s, 0x08); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_192_192_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_192_192_RATE); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + mlen -= SCHWAEMM_192_192_RATE; + } + if (mlen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + memcpy(c, block, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return 0; +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_192_192_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_192_192_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + clen -= SCHWAEMM_192_192_RATE; + } + if (clen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_192_192_RIGHT(s), c, SCHWAEMM_192_192_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RATE 16 + +/** + * \brief Pointer to the left of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RIGHT(s) \ + (SCHWAEMM_128_128_LEFT(s) + SCHWAEMM_128_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_128_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[0] = s[2] ^ s[4]; \ + s[1] = s[3] ^ s[5]; \ + s[2] ^= t0 ^ s[6]; \ + s[3] ^= t1 ^ s[7]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_128_128_authenticate + (uint32_t s[SPARKLE_256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + ad += SCHWAEMM_128_128_RATE; + adlen -= SCHWAEMM_128_128_RATE; + } + if (adlen == SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_128_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + uint8_t block[SCHWAEMM_128_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + memcpy(c, block, SCHWAEMM_128_128_RATE); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + mlen -= SCHWAEMM_128_128_RATE; + } + if (mlen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + memcpy(c, block, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_256(s, 10); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return 0; +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_128_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_128_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + clen -= SCHWAEMM_128_128_RATE; + } + if (clen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_128_128_RIGHT(s), c, SCHWAEMM_128_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RIGHT(s) \ + (SCHWAEMM_256_256_LEFT(s) + SCHWAEMM_256_256_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_256_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[15] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[12]; \ + s[5] ^= t1 ^ s[13]; \ + s[6] ^= t2 ^ s[14]; \ + s[7] ^= t3 ^ s[15]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_256_authenticate + (uint32_t s[SPARKLE_512_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + ad += SCHWAEMM_256_256_RATE; + adlen -= SCHWAEMM_256_256_RATE; + } + if (adlen == SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x11); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_256_rho(s, 0x10); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_256_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + memcpy(c, block, SCHWAEMM_256_256_RATE); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + mlen -= SCHWAEMM_256_256_RATE; + } + if (mlen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + memcpy(c, block, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_512(s, 12); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return 0; +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_256_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_256_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + clen -= SCHWAEMM_256_256_RATE; + } + if (clen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_256_RIGHT(s), c, SCHWAEMM_256_256_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Esch256. + */ +#define ESCH_256_RATE 16 + +/** + * \brief Perform the M3 step for Esch256 to mix the input with the state. + * + * \param s SPARKLE-384 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_256_m3(s, block, domain) \ + do { \ + uint32_t tx = (block)[0] ^ (block)[2]; \ + uint32_t ty = (block)[1] ^ (block)[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= (block)[0] ^ ty; \ + s[1] ^= (block)[1] ^ tx; \ + s[2] ^= (block)[2] ^ ty; \ + s[3] ^= (block)[3] ^ tx; \ + if ((domain) != 0) \ + s[5] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + } while (0) + +/** @cond esch_256 */ + +/** + * \brief Word-based state for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_384_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_256_hash_state_wt; + +/** @endcond */ + +int esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x00); + sparkle_384(s, 7); + in += ESCH_256_RATE; + inlen -= ESCH_256_RATE; + } + if (inlen == ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(s, block, 0x01); + } + sparkle_384(s, 11); + memcpy(out, s, ESCH_256_RATE); + sparkle_384(s, 7); + memcpy(out + ESCH_256_RATE, s, ESCH_256_RATE); + return 0; +} + +void esch_256_hash_init(esch_256_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_256_hash_state_t)); +} + +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x00); + sparkle_384(st->s.state, 7); + st->s.count = 0; + } + temp = ESCH_256_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(st->s.state, st->s.block, 0x01); + } + sparkle_384(st->s.state, 11); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_256_RATE); + sparkle_384(st->s.state, 7); + memcpy(out + ESCH_256_RATE, st->s.state, ESCH_256_RATE); +} + +/** + * \brief Rate at which bytes are processed by Esch384. + */ +#define ESCH_384_RATE 16 + +/** + * \brief Perform the M4 step for Esch384 to mix the input with the state. + * + * \param s SPARKLE-512 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_384_m4(s, block, domain) \ + do { \ + uint32_t tx = block[0] ^ block[2]; \ + uint32_t ty = block[1] ^ block[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= block[0] ^ ty; \ + s[1] ^= block[1] ^ tx; \ + s[2] ^= block[2] ^ ty; \ + s[3] ^= block[3] ^ tx; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + s[6] ^= ty; \ + s[7] ^= tx; \ + } while (0) + +/** @cond esch_384 */ + +/** + * \brief Word-based state for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_512_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_384_hash_state_wt; + +/** @endcond */ + +int esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x00); + sparkle_512(s, 8); + in += ESCH_384_RATE; + inlen -= ESCH_384_RATE; + } + if (inlen == ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(s, block, 0x01); + } + sparkle_512(s, 12); + memcpy(out, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE * 2, s, ESCH_384_RATE); + return 0; +} + +void esch_384_hash_init(esch_384_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_384_hash_state_t)); +} + +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x00); + sparkle_512(st->s.state, 8); + st->s.count = 0; + } + temp = ESCH_384_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(st->s.state, st->s.block, 0x01); + } + sparkle_512(st->s.state, 12); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE * 2, st->s.state, ESCH_384_RATE); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.h new file mode 100644 index 0000000..dd0999e --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm192192v1/rhys/sparkle.h @@ -0,0 +1,515 @@ +/* + * 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_SPARKLE_H +#define LWCRYPTO_SPARKLE_H + +#include "aead-common.h" + +/** + * \file sparkle.h + * \brief Encryption and hash algorithms based on the SPARKLE permutation. + * + * SPARKLE is a family of encryption and hash algorithms that are based + * around the SPARKLE permutation. There are three versions of the + * permutation with 256-bit, 384-bit, and 512-bit state sizes. + * The algorithms in the family are: + * + * \li Schwaemm256-128 with a 128-bit key, a 256-bit nonce, and a 128-bit tag. + * This is the primary encryption algorithm in the family. + * \li Schwaemm192-192 with a 192-bit key, a 192-bit nonce, and a 192-bit tag. + * \li Schwaemm128-128 with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * \li Schwaemm256-256 with a 256-bit key, a 256-bit nonce, and a 256-bit tag. + * \li Esch256 hash algorithm with a 256-bit digest output. This is the + * primary hash algorithm in the family. + * \li Esch384 hash algorithm with a 384-bit digest output. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_NONCE_SIZE 32 + +/** + * \brief Size of the key for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash output for Esch256. + */ +#define ESCH_256_HASH_SIZE 32 + +/** + * \brief Size of the hash output for Esch384. + */ +#define ESCH_384_HASH_SIZE 48 + +/** + * \brief Meta-information block for the Schwaemm256-128 cipher. + */ +extern aead_cipher_t const schwaemm_256_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm192-192 cipher. + */ +extern aead_cipher_t const schwaemm_192_192_cipher; + +/** + * \brief Meta-information block for the Schwaemm128-128 cipher. + */ +extern aead_cipher_t const schwaemm_128_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm256-256 cipher. + */ +extern aead_cipher_t const schwaemm_256_256_cipher; + +/** + * \brief Meta-information block for the Esch256 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_256_hash_algorithm; + +/** + * \brief Meta-information block for the Esch384 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_384_hash_algorithm; + +/** + * \brief State information for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_256_hash_state_t; + +/** + * \brief State information for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[64]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_384_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_128_aead_decrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_128_aead_encrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm192-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 24 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_192_192_aead_decrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm192-192. + * + * \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 - not used by this algorithm. + * \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 24 byte 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 which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa schwaemm_192_192_aead_encrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm128-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_128_128_aead_decrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm128-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_128_128_aead_encrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_256_aead_decrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_256_aead_encrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Hashes a block of input data with Esch256 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_256_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 esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch256 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_256_hash_update(), esch_256_hash_finalize(), esch_256_hash() + */ +void esch_256_hash_init(esch_256_hash_state_t *state); + +/** + * \brief Updates an Esch256 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. + * + * \sa esch_256_hash_init(), esch_256_hash_finalize() + */ +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch256 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa esch_256_hash_init(), esch_256_hash_update() + */ +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with Esch384 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_384_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 esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch384 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_384_hash_update(), esch_384_hash_finalize(), esch_384_hash() + */ +void esch_384_hash_init(esch_384_hash_state_t *state); + +/** + * \brief Updates an Esch384 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. + * + * \sa esch_384_hash_init(), esch_384_hash_finalize() + */ +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch384 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 48-byte hash value. + * + * \sa esch_384_hash_init(), esch_384_hash_update() + */ +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.c b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.h b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/api.h b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/api.h new file mode 100644 index 0000000..420cea6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 32 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/encrypt.c b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/encrypt.c new file mode 100644 index 0000000..6063cb6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sparkle.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 schwaemm_256_128_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 schwaemm_256_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.c new file mode 100644 index 0000000..822af50 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.c @@ -0,0 +1,366 @@ +/* + * 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 "internal-sparkle.h" + +/* The 8 basic round constants from the specification */ +#define RC_0 0xB7E15162 +#define RC_1 0xBF715880 +#define RC_2 0x38B4DA56 +#define RC_3 0x324E7738 +#define RC_4 0xBB1185EB +#define RC_5 0x4F7C7B57 +#define RC_6 0xCFBFA1C8 +#define RC_7 0xC2B3293D + +/* Round constants for all SPARKLE steps; maximum of 12 for SPARKLE-512 */ +static uint32_t const sparkle_rc[12] = { + RC_0, RC_1, RC_2, RC_3, RC_4, RC_5, RC_6, RC_7, + RC_0, RC_1, RC_2, RC_3 +}; + +/** + * \brief Alzette block cipher that implements the ARXbox layer of the + * SPARKLE permutation. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param k 32-bit round key. + */ +#define alzette(x, y, k) \ + do { \ + (x) += leftRotate1((y)); \ + (y) ^= leftRotate8((x)); \ + (x) ^= (k); \ + (x) += leftRotate15((y)); \ + (y) ^= leftRotate15((x)); \ + (x) ^= (k); \ + (x) += (y); \ + (y) ^= leftRotate1((x)); \ + (x) ^= (k); \ + (x) += leftRotate8((y)); \ + (y) ^= leftRotate16((x)); \ + (x) ^= (k); \ + } while (0) + +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-256 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + + /* Linear layer */ + tx = x0 ^ x1; + ty = y0 ^ y1; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x3 ^ x1 ^ ty; + x3 = x1; + y0 = y3 ^ y1 ^ tx; + y3 = y1; + x1 = x2 ^ tw ^ ty; + x2 = tw; + y1 = y2 ^ tz ^ tx; + y2 = tz; + } + + /* Write the local variables back to the SPARKLE-256 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); +#endif +} + +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t y0, y1, y2, y3, y4, y5; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-384 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2; + ty = y0 ^ y1 ^ y2; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x4 ^ x1 ^ ty; + x4 = x1; + y0 = y4 ^ y1 ^ tx; + y4 = y1; + x1 = x5 ^ x2 ^ ty; + x5 = x2; + y1 = y5 ^ y2 ^ tx; + y5 = y2; + x2 = x3 ^ tw ^ ty; + x3 = tw; + y2 = y3 ^ tz ^ tx; + y3 = tz; + } + + /* Write the local variables back to the SPARKLE-384 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); +#endif +} + +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y0, y1, y2, y3, y4, y5, y6, y7; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-512 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; + x6 = s[12]; + y6 = s[13]; + x7 = s[14]; + y7 = s[15]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); + x6 = le_load_word32((const uint8_t *)&(s[12])); + y6 = le_load_word32((const uint8_t *)&(s[13])); + x7 = le_load_word32((const uint8_t *)&(s[14])); + y7 = le_load_word32((const uint8_t *)&(s[15])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + alzette(x6, y6, RC_6); + alzette(x7, y7, RC_7); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2 ^ x3; + ty = y0 ^ y1 ^ y2 ^ y3; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x5 ^ x1 ^ ty; + x5 = x1; + y0 = y5 ^ y1 ^ tx; + y5 = y1; + x1 = x6 ^ x2 ^ ty; + x6 = x2; + y1 = y6 ^ y2 ^ tx; + y6 = y2; + x2 = x7 ^ x3 ^ ty; + x7 = x3; + y2 = y7 ^ y3 ^ tx; + y7 = y3; + x3 = x4 ^ tw ^ ty; + x4 = tw; + y3 = y4 ^ tz ^ tx; + y4 = tz; + } + + /* Write the local variables back to the SPARKLE-512 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; + s[12] = x6; + s[13] = y6; + s[14] = x7; + s[15] = y7; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); + le_store_word32((uint8_t *)&(s[12]), x6); + le_store_word32((uint8_t *)&(s[13]), y6); + le_store_word32((uint8_t *)&(s[14]), x7); + le_store_word32((uint8_t *)&(s[15]), y7); +#endif +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.h new file mode 100644 index 0000000..fbdabc1 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-sparkle.h @@ -0,0 +1,82 @@ +/* + * 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_SPARKLE_H +#define LW_INTERNAL_SPARKLE_H + +#include "internal-util.h" + +/** + * \file internal-sparkle.h + * \brief Internal implementation of the SPARKLE permutation. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for SPARKLE-256. + */ +#define SPARKLE_256_STATE_SIZE 8 + +/** + * \brief Size of the state for SPARKLE-384. + */ +#define SPARKLE_384_STATE_SIZE 12 + +/** + * \brief Size of the state for SPARKLE-512. + */ +#define SPARKLE_512_STATE_SIZE 16 + +/** + * \brief Performs the SPARKLE-256 permutation. + * + * \param s The words of the SPARKLE-256 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 10. + */ +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-384 permutation. + * + * \param s The words of the SPARKLE-384 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 11. + */ +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-512 permutation. + * + * \param s The words of the SPARKLE-512 state in little-endian byte order. + * \param steps The number of steps to perform, 8 or 12. + */ +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-util.h b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.c new file mode 100644 index 0000000..b357de6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.c @@ -0,0 +1,1123 @@ +/* + * 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 "sparkle.h" +#include "internal-sparkle.h" +#include + +aead_cipher_t const schwaemm_256_128_cipher = { + "Schwaemm256-128", + SCHWAEMM_256_128_KEY_SIZE, + SCHWAEMM_256_128_NONCE_SIZE, + SCHWAEMM_256_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_128_aead_encrypt, + schwaemm_256_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_192_192_cipher = { + "Schwaemm192-192", + SCHWAEMM_192_192_KEY_SIZE, + SCHWAEMM_192_192_NONCE_SIZE, + SCHWAEMM_192_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_192_192_aead_encrypt, + schwaemm_192_192_aead_decrypt +}; + +aead_cipher_t const schwaemm_128_128_cipher = { + "Schwaemm128-128", + SCHWAEMM_128_128_KEY_SIZE, + SCHWAEMM_128_128_NONCE_SIZE, + SCHWAEMM_128_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_128_128_aead_encrypt, + schwaemm_128_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_256_256_cipher = { + "Schwaemm256-256", + SCHWAEMM_256_256_KEY_SIZE, + SCHWAEMM_256_256_NONCE_SIZE, + SCHWAEMM_256_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_256_aead_encrypt, + schwaemm_256_256_aead_decrypt +}; + +aead_hash_algorithm_t const esch_256_hash_algorithm = { + "Esch256", + sizeof(esch_256_hash_state_t), + ESCH_256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_256_hash, + (aead_hash_init_t)esch_256_hash_init, + (aead_hash_update_t)esch_256_hash_update, + (aead_hash_finalize_t)esch_256_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +aead_hash_algorithm_t const esch_384_hash_algorithm = { + "Esch384", + sizeof(esch_384_hash_state_t), + ESCH_384_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_384_hash, + (aead_hash_init_t)esch_384_hash_init, + (aead_hash_update_t)esch_384_hash_update, + (aead_hash_finalize_t)esch_384_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +/** + * \def DOMAIN(value) + * \brief Build a domain separation value as a 32-bit word. + * + * \param value The base value. + * \return The domain separation value as a 32-bit word. + */ +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define DOMAIN(value) (((uint32_t)(value)) << 24) +#else +#define DOMAIN(value) (value) +#endif + +/** + * \brief Rate at which bytes are processed by Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RIGHT(s) \ + (SCHWAEMM_256_128_LEFT(s) + SCHWAEMM_256_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[8]; \ + s[5] ^= t1 ^ s[9]; \ + s[6] ^= t2 ^ s[10]; \ + s[7] ^= t3 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_128_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_256_128_RATE; + adlen -= SCHWAEMM_256_128_RATE; + } + if (adlen == SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_256_128_RATE); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + mlen -= SCHWAEMM_256_128_RATE; + } + if (mlen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + memcpy(c, block, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return 0; +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + clen -= SCHWAEMM_256_128_RATE; + } + if (clen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_128_RIGHT(s), c, SCHWAEMM_256_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RATE 24 + +/** + * \brief Pointer to the left of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RIGHT(s) \ + (SCHWAEMM_192_192_LEFT(s) + SCHWAEMM_192_192_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_192_192_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[3] ^ s[6]; \ + s[1] = s[4] ^ s[7]; \ + s[2] = s[5] ^ s[8]; \ + s[3] ^= t0 ^ s[9]; \ + s[4] ^= t1 ^ s[10]; \ + s[5] ^= t2 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_192_192_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_192_192_RATE; + adlen -= SCHWAEMM_192_192_RATE; + } + if (adlen == SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x09); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_192_192_rho(s, 0x08); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_192_192_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_192_192_RATE); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + mlen -= SCHWAEMM_192_192_RATE; + } + if (mlen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + memcpy(c, block, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return 0; +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_192_192_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_192_192_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + clen -= SCHWAEMM_192_192_RATE; + } + if (clen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_192_192_RIGHT(s), c, SCHWAEMM_192_192_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RATE 16 + +/** + * \brief Pointer to the left of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RIGHT(s) \ + (SCHWAEMM_128_128_LEFT(s) + SCHWAEMM_128_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_128_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[0] = s[2] ^ s[4]; \ + s[1] = s[3] ^ s[5]; \ + s[2] ^= t0 ^ s[6]; \ + s[3] ^= t1 ^ s[7]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_128_128_authenticate + (uint32_t s[SPARKLE_256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + ad += SCHWAEMM_128_128_RATE; + adlen -= SCHWAEMM_128_128_RATE; + } + if (adlen == SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_128_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + uint8_t block[SCHWAEMM_128_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + memcpy(c, block, SCHWAEMM_128_128_RATE); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + mlen -= SCHWAEMM_128_128_RATE; + } + if (mlen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + memcpy(c, block, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_256(s, 10); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return 0; +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_128_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_128_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + clen -= SCHWAEMM_128_128_RATE; + } + if (clen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_128_128_RIGHT(s), c, SCHWAEMM_128_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RIGHT(s) \ + (SCHWAEMM_256_256_LEFT(s) + SCHWAEMM_256_256_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_256_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[15] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[12]; \ + s[5] ^= t1 ^ s[13]; \ + s[6] ^= t2 ^ s[14]; \ + s[7] ^= t3 ^ s[15]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_256_authenticate + (uint32_t s[SPARKLE_512_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + ad += SCHWAEMM_256_256_RATE; + adlen -= SCHWAEMM_256_256_RATE; + } + if (adlen == SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x11); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_256_rho(s, 0x10); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_256_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + memcpy(c, block, SCHWAEMM_256_256_RATE); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + mlen -= SCHWAEMM_256_256_RATE; + } + if (mlen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + memcpy(c, block, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_512(s, 12); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return 0; +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_256_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_256_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + clen -= SCHWAEMM_256_256_RATE; + } + if (clen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_256_RIGHT(s), c, SCHWAEMM_256_256_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Esch256. + */ +#define ESCH_256_RATE 16 + +/** + * \brief Perform the M3 step for Esch256 to mix the input with the state. + * + * \param s SPARKLE-384 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_256_m3(s, block, domain) \ + do { \ + uint32_t tx = (block)[0] ^ (block)[2]; \ + uint32_t ty = (block)[1] ^ (block)[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= (block)[0] ^ ty; \ + s[1] ^= (block)[1] ^ tx; \ + s[2] ^= (block)[2] ^ ty; \ + s[3] ^= (block)[3] ^ tx; \ + if ((domain) != 0) \ + s[5] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + } while (0) + +/** @cond esch_256 */ + +/** + * \brief Word-based state for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_384_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_256_hash_state_wt; + +/** @endcond */ + +int esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x00); + sparkle_384(s, 7); + in += ESCH_256_RATE; + inlen -= ESCH_256_RATE; + } + if (inlen == ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(s, block, 0x01); + } + sparkle_384(s, 11); + memcpy(out, s, ESCH_256_RATE); + sparkle_384(s, 7); + memcpy(out + ESCH_256_RATE, s, ESCH_256_RATE); + return 0; +} + +void esch_256_hash_init(esch_256_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_256_hash_state_t)); +} + +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x00); + sparkle_384(st->s.state, 7); + st->s.count = 0; + } + temp = ESCH_256_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(st->s.state, st->s.block, 0x01); + } + sparkle_384(st->s.state, 11); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_256_RATE); + sparkle_384(st->s.state, 7); + memcpy(out + ESCH_256_RATE, st->s.state, ESCH_256_RATE); +} + +/** + * \brief Rate at which bytes are processed by Esch384. + */ +#define ESCH_384_RATE 16 + +/** + * \brief Perform the M4 step for Esch384 to mix the input with the state. + * + * \param s SPARKLE-512 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_384_m4(s, block, domain) \ + do { \ + uint32_t tx = block[0] ^ block[2]; \ + uint32_t ty = block[1] ^ block[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= block[0] ^ ty; \ + s[1] ^= block[1] ^ tx; \ + s[2] ^= block[2] ^ ty; \ + s[3] ^= block[3] ^ tx; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + s[6] ^= ty; \ + s[7] ^= tx; \ + } while (0) + +/** @cond esch_384 */ + +/** + * \brief Word-based state for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_512_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_384_hash_state_wt; + +/** @endcond */ + +int esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x00); + sparkle_512(s, 8); + in += ESCH_384_RATE; + inlen -= ESCH_384_RATE; + } + if (inlen == ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(s, block, 0x01); + } + sparkle_512(s, 12); + memcpy(out, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE * 2, s, ESCH_384_RATE); + return 0; +} + +void esch_384_hash_init(esch_384_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_384_hash_state_t)); +} + +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x00); + sparkle_512(st->s.state, 8); + st->s.count = 0; + } + temp = ESCH_384_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(st->s.state, st->s.block, 0x01); + } + sparkle_512(st->s.state, 12); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE * 2, st->s.state, ESCH_384_RATE); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.h new file mode 100644 index 0000000..dd0999e --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256128v1/rhys/sparkle.h @@ -0,0 +1,515 @@ +/* + * 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_SPARKLE_H +#define LWCRYPTO_SPARKLE_H + +#include "aead-common.h" + +/** + * \file sparkle.h + * \brief Encryption and hash algorithms based on the SPARKLE permutation. + * + * SPARKLE is a family of encryption and hash algorithms that are based + * around the SPARKLE permutation. There are three versions of the + * permutation with 256-bit, 384-bit, and 512-bit state sizes. + * The algorithms in the family are: + * + * \li Schwaemm256-128 with a 128-bit key, a 256-bit nonce, and a 128-bit tag. + * This is the primary encryption algorithm in the family. + * \li Schwaemm192-192 with a 192-bit key, a 192-bit nonce, and a 192-bit tag. + * \li Schwaemm128-128 with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * \li Schwaemm256-256 with a 256-bit key, a 256-bit nonce, and a 256-bit tag. + * \li Esch256 hash algorithm with a 256-bit digest output. This is the + * primary hash algorithm in the family. + * \li Esch384 hash algorithm with a 384-bit digest output. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_NONCE_SIZE 32 + +/** + * \brief Size of the key for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash output for Esch256. + */ +#define ESCH_256_HASH_SIZE 32 + +/** + * \brief Size of the hash output for Esch384. + */ +#define ESCH_384_HASH_SIZE 48 + +/** + * \brief Meta-information block for the Schwaemm256-128 cipher. + */ +extern aead_cipher_t const schwaemm_256_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm192-192 cipher. + */ +extern aead_cipher_t const schwaemm_192_192_cipher; + +/** + * \brief Meta-information block for the Schwaemm128-128 cipher. + */ +extern aead_cipher_t const schwaemm_128_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm256-256 cipher. + */ +extern aead_cipher_t const schwaemm_256_256_cipher; + +/** + * \brief Meta-information block for the Esch256 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_256_hash_algorithm; + +/** + * \brief Meta-information block for the Esch384 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_384_hash_algorithm; + +/** + * \brief State information for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_256_hash_state_t; + +/** + * \brief State information for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[64]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_384_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_128_aead_decrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_128_aead_encrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm192-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 24 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_192_192_aead_decrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm192-192. + * + * \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 - not used by this algorithm. + * \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 24 byte 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 which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa schwaemm_192_192_aead_encrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm128-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_128_128_aead_decrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm128-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_128_128_aead_encrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_256_aead_decrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_256_aead_encrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Hashes a block of input data with Esch256 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_256_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 esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch256 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_256_hash_update(), esch_256_hash_finalize(), esch_256_hash() + */ +void esch_256_hash_init(esch_256_hash_state_t *state); + +/** + * \brief Updates an Esch256 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. + * + * \sa esch_256_hash_init(), esch_256_hash_finalize() + */ +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch256 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa esch_256_hash_init(), esch_256_hash_update() + */ +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with Esch384 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_384_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 esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch384 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_384_hash_update(), esch_384_hash_finalize(), esch_384_hash() + */ +void esch_384_hash_init(esch_384_hash_state_t *state); + +/** + * \brief Updates an Esch384 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. + * + * \sa esch_384_hash_init(), esch_384_hash_finalize() + */ +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch384 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 48-byte hash value. + * + * \sa esch_384_hash_init(), esch_384_hash_update() + */ +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.c b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.h b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/api.h b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/api.h new file mode 100644 index 0000000..c11fc10 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 32 +#define CRYPTO_ABYTES 32 +#define CRYPTO_NOOVERLAP 1 diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/encrypt.c b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/encrypt.c new file mode 100644 index 0000000..c5f15f6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sparkle.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 schwaemm_256_256_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 schwaemm_256_256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.c new file mode 100644 index 0000000..822af50 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.c @@ -0,0 +1,366 @@ +/* + * 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 "internal-sparkle.h" + +/* The 8 basic round constants from the specification */ +#define RC_0 0xB7E15162 +#define RC_1 0xBF715880 +#define RC_2 0x38B4DA56 +#define RC_3 0x324E7738 +#define RC_4 0xBB1185EB +#define RC_5 0x4F7C7B57 +#define RC_6 0xCFBFA1C8 +#define RC_7 0xC2B3293D + +/* Round constants for all SPARKLE steps; maximum of 12 for SPARKLE-512 */ +static uint32_t const sparkle_rc[12] = { + RC_0, RC_1, RC_2, RC_3, RC_4, RC_5, RC_6, RC_7, + RC_0, RC_1, RC_2, RC_3 +}; + +/** + * \brief Alzette block cipher that implements the ARXbox layer of the + * SPARKLE permutation. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param k 32-bit round key. + */ +#define alzette(x, y, k) \ + do { \ + (x) += leftRotate1((y)); \ + (y) ^= leftRotate8((x)); \ + (x) ^= (k); \ + (x) += leftRotate15((y)); \ + (y) ^= leftRotate15((x)); \ + (x) ^= (k); \ + (x) += (y); \ + (y) ^= leftRotate1((x)); \ + (x) ^= (k); \ + (x) += leftRotate8((y)); \ + (y) ^= leftRotate16((x)); \ + (x) ^= (k); \ + } while (0) + +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-256 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + + /* Linear layer */ + tx = x0 ^ x1; + ty = y0 ^ y1; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x3 ^ x1 ^ ty; + x3 = x1; + y0 = y3 ^ y1 ^ tx; + y3 = y1; + x1 = x2 ^ tw ^ ty; + x2 = tw; + y1 = y2 ^ tz ^ tx; + y2 = tz; + } + + /* Write the local variables back to the SPARKLE-256 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); +#endif +} + +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5; + uint32_t y0, y1, y2, y3, y4, y5; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-384 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2; + ty = y0 ^ y1 ^ y2; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x4 ^ x1 ^ ty; + x4 = x1; + y0 = y4 ^ y1 ^ tx; + y4 = y1; + x1 = x5 ^ x2 ^ ty; + x5 = x2; + y1 = y5 ^ y2 ^ tx; + y5 = y2; + x2 = x3 ^ tw ^ ty; + x3 = tw; + y2 = y3 ^ tz ^ tx; + y3 = tz; + } + + /* Write the local variables back to the SPARKLE-384 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); +#endif +} + +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y0, y1, y2, y3, y4, y5, y6, y7; + uint32_t tx, ty, tz, tw; + unsigned step; + + /* Load the SPARKLE-512 state up into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x0 = s[0]; + y0 = s[1]; + x1 = s[2]; + y1 = s[3]; + x2 = s[4]; + y2 = s[5]; + x3 = s[6]; + y3 = s[7]; + x4 = s[8]; + y4 = s[9]; + x5 = s[10]; + y5 = s[11]; + x6 = s[12]; + y6 = s[13]; + x7 = s[14]; + y7 = s[15]; +#else + x0 = le_load_word32((const uint8_t *)&(s[0])); + y0 = le_load_word32((const uint8_t *)&(s[1])); + x1 = le_load_word32((const uint8_t *)&(s[2])); + y1 = le_load_word32((const uint8_t *)&(s[3])); + x2 = le_load_word32((const uint8_t *)&(s[4])); + y2 = le_load_word32((const uint8_t *)&(s[5])); + x3 = le_load_word32((const uint8_t *)&(s[6])); + y3 = le_load_word32((const uint8_t *)&(s[7])); + x4 = le_load_word32((const uint8_t *)&(s[8])); + y4 = le_load_word32((const uint8_t *)&(s[9])); + x5 = le_load_word32((const uint8_t *)&(s[10])); + y5 = le_load_word32((const uint8_t *)&(s[11])); + x6 = le_load_word32((const uint8_t *)&(s[12])); + y6 = le_load_word32((const uint8_t *)&(s[13])); + x7 = le_load_word32((const uint8_t *)&(s[14])); + y7 = le_load_word32((const uint8_t *)&(s[15])); +#endif + + /* Perform all requested steps */ + for (step = 0; step < steps; ++step) { + /* Add round constants */ + y0 ^= sparkle_rc[step]; + y1 ^= step; + + /* ARXbox layer */ + alzette(x0, y0, RC_0); + alzette(x1, y1, RC_1); + alzette(x2, y2, RC_2); + alzette(x3, y3, RC_3); + alzette(x4, y4, RC_4); + alzette(x5, y5, RC_5); + alzette(x6, y6, RC_6); + alzette(x7, y7, RC_7); + + /* Linear layer */ + tx = x0 ^ x1 ^ x2 ^ x3; + ty = y0 ^ y1 ^ y2 ^ y3; + tw = x0; + tz = y0; + tx = leftRotate16(tx ^ (tx << 16)); + ty = leftRotate16(ty ^ (ty << 16)); + x0 = x5 ^ x1 ^ ty; + x5 = x1; + y0 = y5 ^ y1 ^ tx; + y5 = y1; + x1 = x6 ^ x2 ^ ty; + x6 = x2; + y1 = y6 ^ y2 ^ tx; + y6 = y2; + x2 = x7 ^ x3 ^ ty; + x7 = x3; + y2 = y7 ^ y3 ^ tx; + y7 = y3; + x3 = x4 ^ tw ^ ty; + x4 = tw; + y3 = y4 ^ tz ^ tx; + y4 = tz; + } + + /* Write the local variables back to the SPARKLE-512 state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s[0] = x0; + s[1] = y0; + s[2] = x1; + s[3] = y1; + s[4] = x2; + s[5] = y2; + s[6] = x3; + s[7] = y3; + s[8] = x4; + s[9] = y4; + s[10] = x5; + s[11] = y5; + s[12] = x6; + s[13] = y6; + s[14] = x7; + s[15] = y7; +#else + le_store_word32((uint8_t *)&(s[0]), x0); + le_store_word32((uint8_t *)&(s[1]), y0); + le_store_word32((uint8_t *)&(s[2]), x1); + le_store_word32((uint8_t *)&(s[3]), y1); + le_store_word32((uint8_t *)&(s[4]), x2); + le_store_word32((uint8_t *)&(s[5]), y2); + le_store_word32((uint8_t *)&(s[6]), x3); + le_store_word32((uint8_t *)&(s[7]), y3); + le_store_word32((uint8_t *)&(s[8]), x4); + le_store_word32((uint8_t *)&(s[9]), y4); + le_store_word32((uint8_t *)&(s[10]), x5); + le_store_word32((uint8_t *)&(s[11]), y5); + le_store_word32((uint8_t *)&(s[12]), x6); + le_store_word32((uint8_t *)&(s[13]), y6); + le_store_word32((uint8_t *)&(s[14]), x7); + le_store_word32((uint8_t *)&(s[15]), y7); +#endif +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.h new file mode 100644 index 0000000..fbdabc1 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-sparkle.h @@ -0,0 +1,82 @@ +/* + * 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_SPARKLE_H +#define LW_INTERNAL_SPARKLE_H + +#include "internal-util.h" + +/** + * \file internal-sparkle.h + * \brief Internal implementation of the SPARKLE permutation. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for SPARKLE-256. + */ +#define SPARKLE_256_STATE_SIZE 8 + +/** + * \brief Size of the state for SPARKLE-384. + */ +#define SPARKLE_384_STATE_SIZE 12 + +/** + * \brief Size of the state for SPARKLE-512. + */ +#define SPARKLE_512_STATE_SIZE 16 + +/** + * \brief Performs the SPARKLE-256 permutation. + * + * \param s The words of the SPARKLE-256 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 10. + */ +void sparkle_256(uint32_t s[SPARKLE_256_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-384 permutation. + * + * \param s The words of the SPARKLE-384 state in little-endian byte order. + * \param steps The number of steps to perform, 7 or 11. + */ +void sparkle_384(uint32_t s[SPARKLE_384_STATE_SIZE], unsigned steps); + +/** + * \brief Performs the SPARKLE-512 permutation. + * + * \param s The words of the SPARKLE-512 state in little-endian byte order. + * \param steps The number of steps to perform, 8 or 12. + */ +void sparkle_512(uint32_t s[SPARKLE_512_STATE_SIZE], unsigned steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-util.h b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.c b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.c new file mode 100644 index 0000000..b357de6 --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.c @@ -0,0 +1,1123 @@ +/* + * 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 "sparkle.h" +#include "internal-sparkle.h" +#include + +aead_cipher_t const schwaemm_256_128_cipher = { + "Schwaemm256-128", + SCHWAEMM_256_128_KEY_SIZE, + SCHWAEMM_256_128_NONCE_SIZE, + SCHWAEMM_256_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_128_aead_encrypt, + schwaemm_256_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_192_192_cipher = { + "Schwaemm192-192", + SCHWAEMM_192_192_KEY_SIZE, + SCHWAEMM_192_192_NONCE_SIZE, + SCHWAEMM_192_192_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_192_192_aead_encrypt, + schwaemm_192_192_aead_decrypt +}; + +aead_cipher_t const schwaemm_128_128_cipher = { + "Schwaemm128-128", + SCHWAEMM_128_128_KEY_SIZE, + SCHWAEMM_128_128_NONCE_SIZE, + SCHWAEMM_128_128_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_128_128_aead_encrypt, + schwaemm_128_128_aead_decrypt +}; + +aead_cipher_t const schwaemm_256_256_cipher = { + "Schwaemm256-256", + SCHWAEMM_256_256_KEY_SIZE, + SCHWAEMM_256_256_NONCE_SIZE, + SCHWAEMM_256_256_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + schwaemm_256_256_aead_encrypt, + schwaemm_256_256_aead_decrypt +}; + +aead_hash_algorithm_t const esch_256_hash_algorithm = { + "Esch256", + sizeof(esch_256_hash_state_t), + ESCH_256_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_256_hash, + (aead_hash_init_t)esch_256_hash_init, + (aead_hash_update_t)esch_256_hash_update, + (aead_hash_finalize_t)esch_256_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +aead_hash_algorithm_t const esch_384_hash_algorithm = { + "Esch384", + sizeof(esch_384_hash_state_t), + ESCH_384_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + esch_384_hash, + (aead_hash_init_t)esch_384_hash_init, + (aead_hash_update_t)esch_384_hash_update, + (aead_hash_finalize_t)esch_384_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +/** + * \def DOMAIN(value) + * \brief Build a domain separation value as a 32-bit word. + * + * \param value The base value. + * \return The domain separation value as a 32-bit word. + */ +#if defined(LW_UTIL_LITTLE_ENDIAN) +#define DOMAIN(value) (((uint32_t)(value)) << 24) +#else +#define DOMAIN(value) (value) +#endif + +/** + * \brief Rate at which bytes are processed by Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_RIGHT(s) \ + (SCHWAEMM_256_128_LEFT(s) + SCHWAEMM_256_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[8]; \ + s[5] ^= t1 ^ s[9]; \ + s[6] ^= t2 ^ s[10]; \ + s[7] ^= t3 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-128. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_128_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_256_128_RATE; + adlen -= SCHWAEMM_256_128_RATE; + } + if (adlen == SCHWAEMM_256_128_RATE) { + schwaemm_256_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_256_128_RATE); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + mlen -= SCHWAEMM_256_128_RATE; + } + if (mlen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + memcpy(c, block, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return 0; +} + +int schwaemm_256_128_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_128_LEFT(s), npub, SCHWAEMM_256_128_NONCE_SIZE); + memcpy(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_256_128_RATE; + m += SCHWAEMM_256_128_RATE; + clen -= SCHWAEMM_256_128_RATE; + } + if (clen == SCHWAEMM_256_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_128_RATE); + schwaemm_256_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_128_RIGHT(s), k, SCHWAEMM_256_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_128_RIGHT(s), c, SCHWAEMM_256_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RATE 24 + +/** + * \brief Pointer to the left of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_RIGHT(s) \ + (SCHWAEMM_192_192_LEFT(s) + SCHWAEMM_192_192_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_192_192_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + if ((domain) != 0) \ + s[11] ^= DOMAIN(domain); \ + s[0] = s[3] ^ s[6]; \ + s[1] = s[4] ^ s[7]; \ + s[2] = s[5] ^ s[8]; \ + s[3] ^= t0 ^ s[9]; \ + s[4] ^= t1 ^ s[10]; \ + s[5] ^= t2 ^ s[11]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm192-192. + * + * \param s SPARKLE-384 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_192_192_authenticate + (uint32_t s[SPARKLE_384_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + ad += SCHWAEMM_192_192_RATE; + adlen -= SCHWAEMM_192_192_RATE; + } + if (adlen == SCHWAEMM_192_192_RATE) { + schwaemm_192_192_rho(s, 0x09); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_192_192_rho(s, 0x08); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint8_t block[SCHWAEMM_192_192_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + memcpy(c, block, SCHWAEMM_192_192_RATE); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + mlen -= SCHWAEMM_192_192_RATE; + } + if (mlen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + memcpy(c, block, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_384(s, 11); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return 0; +} + +int schwaemm_192_192_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) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_192_192_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_192_192_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_192_192_LEFT(s), npub, SCHWAEMM_192_192_NONCE_SIZE); + memcpy(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_KEY_SIZE); + sparkle_384(s, 11); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_192_192_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_192_192_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + sparkle_384(s, 7); + c += SCHWAEMM_192_192_RATE; + m += SCHWAEMM_192_192_RATE; + clen -= SCHWAEMM_192_192_RATE; + } + if (clen == SCHWAEMM_192_192_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_192_192_RATE); + schwaemm_192_192_rho(s, 0x0B); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_192_192_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_192_192_rho(s, 0x0A); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_384(s, 11); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_192_192_RIGHT(s), k, SCHWAEMM_192_192_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_192_192_RIGHT(s), c, SCHWAEMM_192_192_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RATE 16 + +/** + * \brief Pointer to the left of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_RIGHT(s) \ + (SCHWAEMM_128_128_LEFT(s) + SCHWAEMM_128_128_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_128_128_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[0] = s[2] ^ s[4]; \ + s[1] = s[3] ^ s[5]; \ + s[2] ^= t0 ^ s[6]; \ + s[3] ^= t1 ^ s[7]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm128-128. + * + * \param s SPARKLE-256 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_128_128_authenticate + (uint32_t s[SPARKLE_256_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + ad += SCHWAEMM_128_128_RATE; + adlen -= SCHWAEMM_128_128_RATE; + } + if (adlen == SCHWAEMM_128_128_RATE) { + schwaemm_128_128_rho(s, 0x05); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_128_128_rho(s, 0x04); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + uint8_t block[SCHWAEMM_128_128_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + memcpy(c, block, SCHWAEMM_128_128_RATE); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + mlen -= SCHWAEMM_128_128_RATE; + } + if (mlen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + memcpy(c, block, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_256(s, 10); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return 0; +} + +int schwaemm_128_128_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) +{ + uint32_t s[SPARKLE_256_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_128_128_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_128_128_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_128_128_LEFT(s), npub, SCHWAEMM_128_128_NONCE_SIZE); + memcpy(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_KEY_SIZE); + sparkle_256(s, 10); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_128_128_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_128_128_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + sparkle_256(s, 7); + c += SCHWAEMM_128_128_RATE; + m += SCHWAEMM_128_128_RATE; + clen -= SCHWAEMM_128_128_RATE; + } + if (clen == SCHWAEMM_128_128_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_128_128_RATE); + schwaemm_128_128_rho(s, 0x07); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_128_128_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_128_128_rho(s, 0x06); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_256(s, 10); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_128_128_RIGHT(s), k, SCHWAEMM_128_128_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_128_128_RIGHT(s), c, SCHWAEMM_128_128_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RATE 32 + +/** + * \brief Pointer to the left of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_LEFT(s) ((unsigned char *)&(s[0])) + +/** + * \brief Pointer to the right of the state for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_RIGHT(s) \ + (SCHWAEMM_256_256_LEFT(s) + SCHWAEMM_256_256_RATE) + +/** + * \brief Perform the rho1 and rate whitening steps for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param domain Domain separator for this phase. + */ +#define schwaemm_256_256_rho(s, domain) \ + do { \ + uint32_t t0 = s[0]; \ + uint32_t t1 = s[1]; \ + uint32_t t2 = s[2]; \ + uint32_t t3 = s[3]; \ + if ((domain) != 0) \ + s[15] ^= DOMAIN(domain); \ + s[0] = s[4] ^ s[8]; \ + s[1] = s[5] ^ s[9]; \ + s[2] = s[6] ^ s[10]; \ + s[3] = s[7] ^ s[11]; \ + s[4] ^= t0 ^ s[12]; \ + s[5] ^= t1 ^ s[13]; \ + s[6] ^= t2 ^ s[14]; \ + s[7] ^= t3 ^ s[15]; \ + } while (0) + +/** + * \brief Authenticates the associated data for Schwaemm256-256. + * + * \param s SPARKLE-512 state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data; must be >= 1. + */ +static void schwaemm_256_256_authenticate + (uint32_t s[SPARKLE_512_STATE_SIZE], + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen > SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + ad += SCHWAEMM_256_256_RATE; + adlen -= SCHWAEMM_256_256_RATE; + } + if (adlen == SCHWAEMM_256_256_RATE) { + schwaemm_256_256_rho(s, 0x11); + lw_xor_block((unsigned char *)s, ad, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)adlen; + schwaemm_256_256_rho(s, 0x10); + lw_xor_block((unsigned char *)s, ad, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint8_t block[SCHWAEMM_256_256_RATE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) { + while (mlen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + memcpy(c, block, SCHWAEMM_256_256_RATE); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + mlen -= SCHWAEMM_256_256_RATE; + } + if (mlen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (block, (unsigned char *)s, m, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + memcpy(c, block, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_src(block, (unsigned char *)s, m, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + memcpy(c, block, temp); + } + sparkle_512(s, 12); + c += mlen; + } + + /* Generate the authentication tag */ + lw_xor_block_2_src + (c, SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return 0; +} + +int schwaemm_256_256_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) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SCHWAEMM_256_256_TAG_SIZE) + return -1; + *mlen = clen - SCHWAEMM_256_256_TAG_SIZE; + + /* Initialize the state with the nonce and the key */ + memcpy(SCHWAEMM_256_256_LEFT(s), npub, SCHWAEMM_256_256_NONCE_SIZE); + memcpy(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_KEY_SIZE); + sparkle_512(s, 12); + + /* Process the associated data */ + if (adlen > 0) + schwaemm_256_256_authenticate(s, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SCHWAEMM_256_256_TAG_SIZE; + if (clen > 0) { + while (clen > SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x00); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + sparkle_512(s, 8); + c += SCHWAEMM_256_256_RATE; + m += SCHWAEMM_256_256_RATE; + clen -= SCHWAEMM_256_256_RATE; + } + if (clen == SCHWAEMM_256_256_RATE) { + lw_xor_block_2_src + (m, (unsigned char *)s, c, SCHWAEMM_256_256_RATE); + schwaemm_256_256_rho(s, 0x13); + lw_xor_block((unsigned char *)s, m, SCHWAEMM_256_256_RATE); + } else { + unsigned temp = (unsigned)clen; + lw_xor_block_2_src(m, (unsigned char *)s, c, temp); + schwaemm_256_256_rho(s, 0x12); + lw_xor_block((unsigned char *)s, m, temp); + ((unsigned char *)s)[temp] ^= 0x80; + } + sparkle_512(s, 12); + c += clen; + } + + /* Check the authentication tag */ + lw_xor_block(SCHWAEMM_256_256_RIGHT(s), k, SCHWAEMM_256_256_TAG_SIZE); + return aead_check_tag + (mtemp, *mlen, SCHWAEMM_256_256_RIGHT(s), c, SCHWAEMM_256_256_TAG_SIZE); +} + +/** + * \brief Rate at which bytes are processed by Esch256. + */ +#define ESCH_256_RATE 16 + +/** + * \brief Perform the M3 step for Esch256 to mix the input with the state. + * + * \param s SPARKLE-384 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_256_m3(s, block, domain) \ + do { \ + uint32_t tx = (block)[0] ^ (block)[2]; \ + uint32_t ty = (block)[1] ^ (block)[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= (block)[0] ^ ty; \ + s[1] ^= (block)[1] ^ tx; \ + s[2] ^= (block)[2] ^ ty; \ + s[3] ^= (block)[3] ^ tx; \ + if ((domain) != 0) \ + s[5] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + } while (0) + +/** @cond esch_256 */ + +/** + * \brief Word-based state for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_384_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_256_hash_state_wt; + +/** @endcond */ + +int esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_384_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x00); + sparkle_384(s, 7); + in += ESCH_256_RATE; + inlen -= ESCH_256_RATE; + } + if (inlen == ESCH_256_RATE) { + memcpy(block, in, ESCH_256_RATE); + esch_256_m3(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(s, block, 0x01); + } + sparkle_384(s, 11); + memcpy(out, s, ESCH_256_RATE); + sparkle_384(s, 7); + memcpy(out + ESCH_256_RATE, s, ESCH_256_RATE); + return 0; +} + +void esch_256_hash_init(esch_256_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_256_hash_state_t)); +} + +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x00); + sparkle_384(st->s.state, 7); + st->s.count = 0; + } + temp = ESCH_256_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out) +{ + esch_256_hash_state_wt *st = (esch_256_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_256_RATE) { + esch_256_m3(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_256_RATE - temp - 1); + esch_256_m3(st->s.state, st->s.block, 0x01); + } + sparkle_384(st->s.state, 11); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_256_RATE); + sparkle_384(st->s.state, 7); + memcpy(out + ESCH_256_RATE, st->s.state, ESCH_256_RATE); +} + +/** + * \brief Rate at which bytes are processed by Esch384. + */ +#define ESCH_384_RATE 16 + +/** + * \brief Perform the M4 step for Esch384 to mix the input with the state. + * + * \param s SPARKLE-512 state. + * \param block Block of input data that has been padded to the rate. + * \param domain Domain separator for this phase. + */ +#define esch_384_m4(s, block, domain) \ + do { \ + uint32_t tx = block[0] ^ block[2]; \ + uint32_t ty = block[1] ^ block[3]; \ + tx = leftRotate16(tx ^ (tx << 16)); \ + ty = leftRotate16(ty ^ (ty << 16)); \ + s[0] ^= block[0] ^ ty; \ + s[1] ^= block[1] ^ tx; \ + s[2] ^= block[2] ^ ty; \ + s[3] ^= block[3] ^ tx; \ + if ((domain) != 0) \ + s[7] ^= DOMAIN(domain); \ + s[4] ^= ty; \ + s[5] ^= tx; \ + s[6] ^= ty; \ + s[7] ^= tx; \ + } while (0) + +/** @cond esch_384 */ + +/** + * \brief Word-based state for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + uint32_t state[SPARKLE_512_STATE_SIZE]; + uint32_t block[4]; + unsigned char count; + } s; + unsigned long long align; + +} esch_384_hash_state_wt; + +/** @endcond */ + +int esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + uint32_t s[SPARKLE_512_STATE_SIZE]; + uint32_t block[ESCH_256_RATE / 4]; + memset(s, 0, sizeof(s)); + while (inlen > ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x00); + sparkle_512(s, 8); + in += ESCH_384_RATE; + inlen -= ESCH_384_RATE; + } + if (inlen == ESCH_384_RATE) { + memcpy(block, in, ESCH_384_RATE); + esch_384_m4(s, block, 0x02); + } else { + unsigned temp = (unsigned)inlen; + memcpy(block, in, temp); + ((unsigned char *)block)[temp] = 0x80; + memset(((unsigned char *)block) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(s, block, 0x01); + } + sparkle_512(s, 12); + memcpy(out, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE, s, ESCH_384_RATE); + sparkle_512(s, 8); + memcpy(out + ESCH_384_RATE * 2, s, ESCH_384_RATE); + return 0; +} + +void esch_384_hash_init(esch_384_hash_state_t *state) +{ + memset(state, 0, sizeof(esch_384_hash_state_t)); +} + +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + unsigned temp; + while (inlen > 0) { + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x00); + sparkle_512(st->s.state, 8); + st->s.count = 0; + } + temp = ESCH_384_RATE - st->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + memcpy(((unsigned char *)(st->s.block)) + st->s.count, in, temp); + st->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out) +{ + esch_384_hash_state_wt *st = (esch_384_hash_state_wt *)state; + + /* Pad and process the last block */ + if (st->s.count == ESCH_384_RATE) { + esch_384_m4(st->s.state, st->s.block, 0x02); + } else { + unsigned temp = st->s.count; + ((unsigned char *)(st->s.block))[temp] = 0x80; + memset(((unsigned char *)(st->s.block)) + temp + 1, 0, + ESCH_384_RATE - temp - 1); + esch_384_m4(st->s.state, st->s.block, 0x01); + } + sparkle_512(st->s.state, 12); + + /* Generate the final hash value */ + memcpy(out, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE, st->s.state, ESCH_384_RATE); + sparkle_512(st->s.state, 8); + memcpy(out + ESCH_384_RATE * 2, st->s.state, ESCH_384_RATE); +} diff --git a/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.h b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.h new file mode 100644 index 0000000..dd0999e --- /dev/null +++ b/sparkle/Implementations/crypto_aead/schwaemm256256v1/rhys/sparkle.h @@ -0,0 +1,515 @@ +/* + * 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_SPARKLE_H +#define LWCRYPTO_SPARKLE_H + +#include "aead-common.h" + +/** + * \file sparkle.h + * \brief Encryption and hash algorithms based on the SPARKLE permutation. + * + * SPARKLE is a family of encryption and hash algorithms that are based + * around the SPARKLE permutation. There are three versions of the + * permutation with 256-bit, 384-bit, and 512-bit state sizes. + * The algorithms in the family are: + * + * \li Schwaemm256-128 with a 128-bit key, a 256-bit nonce, and a 128-bit tag. + * This is the primary encryption algorithm in the family. + * \li Schwaemm192-192 with a 192-bit key, a 192-bit nonce, and a 192-bit tag. + * \li Schwaemm128-128 with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * \li Schwaemm256-256 with a 256-bit key, a 256-bit nonce, and a 256-bit tag. + * \li Esch256 hash algorithm with a 256-bit digest output. This is the + * primary hash algorithm in the family. + * \li Esch384 hash algorithm with a 384-bit digest output. + * + * References: https://www.cryptolux.org/index.php/Sparkle + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm256-128. + */ +#define SCHWAEMM_256_128_NONCE_SIZE 32 + +/** + * \brief Size of the key for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_KEY_SIZE 24 + +/** + * \brief Size of the authentication tag for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_TAG_SIZE 24 + +/** + * \brief Size of the nonce for Schwaemm192-192. + */ +#define SCHWAEMM_192_192_NONCE_SIZE 24 + +/** + * \brief Size of the key for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Schwaemm128-128. + */ +#define SCHWAEMM_128_128_NONCE_SIZE 16 + +/** + * \brief Size of the key for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_TAG_SIZE 32 + +/** + * \brief Size of the nonce for Schwaemm256-256. + */ +#define SCHWAEMM_256_256_NONCE_SIZE 32 + +/** + * \brief Size of the hash output for Esch256. + */ +#define ESCH_256_HASH_SIZE 32 + +/** + * \brief Size of the hash output for Esch384. + */ +#define ESCH_384_HASH_SIZE 48 + +/** + * \brief Meta-information block for the Schwaemm256-128 cipher. + */ +extern aead_cipher_t const schwaemm_256_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm192-192 cipher. + */ +extern aead_cipher_t const schwaemm_192_192_cipher; + +/** + * \brief Meta-information block for the Schwaemm128-128 cipher. + */ +extern aead_cipher_t const schwaemm_128_128_cipher; + +/** + * \brief Meta-information block for the Schwaemm256-256 cipher. + */ +extern aead_cipher_t const schwaemm_256_256_cipher; + +/** + * \brief Meta-information block for the Esch256 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_256_hash_algorithm; + +/** + * \brief Meta-information block for the Esch384 hash algorithm. + */ +extern aead_hash_algorithm_t const esch_384_hash_algorithm; + +/** + * \brief State information for the Esch256 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_256_hash_state_t; + +/** + * \brief State information for the Esch384 incremental hash mode. + */ +typedef union +{ + struct { + unsigned char state[64]; /**< Current hash state */ + unsigned char block[16]; /**< Partial input data block */ + unsigned char count; /**< Number of bytes in the current block */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} esch_384_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_128_aead_decrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 32 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_128_aead_encrypt() + */ +int schwaemm_256_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm192-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 24 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_192_192_aead_decrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm192-192. + * + * \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 - not used by this algorithm. + * \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 24 byte 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 which must + * be 24 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa schwaemm_192_192_aead_encrypt() + */ +int schwaemm_192_192_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm128-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_128_128_aead_decrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm128-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_128_128_aead_encrypt() + */ +int schwaemm_128_128_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); + +/** + * \brief Encrypts and authenticates a packet with Schwaemm256-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa schwaemm_256_256_aead_decrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Decrypts and authenticates a packet with Schwaemm256-256. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa schwaemm_256_256_aead_encrypt() + */ +int schwaemm_256_256_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); + +/** + * \brief Hashes a block of input data with Esch256 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_256_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 esch_256_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch256 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_256_hash_update(), esch_256_hash_finalize(), esch_256_hash() + */ +void esch_256_hash_init(esch_256_hash_state_t *state); + +/** + * \brief Updates an Esch256 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. + * + * \sa esch_256_hash_init(), esch_256_hash_finalize() + */ +void esch_256_hash_update + (esch_256_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch256 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa esch_256_hash_init(), esch_256_hash_update() + */ +void esch_256_hash_finalize + (esch_256_hash_state_t *state, unsigned char *out); + +/** + * \brief Hashes a block of input data with Esch384 to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * ESCH_384_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 esch_384_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for an Esch384 hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa esch_384_hash_update(), esch_384_hash_finalize(), esch_384_hash() + */ +void esch_384_hash_init(esch_384_hash_state_t *state); + +/** + * \brief Updates an Esch384 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. + * + * \sa esch_384_hash_init(), esch_384_hash_finalize() + */ +void esch_384_hash_update + (esch_384_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from an Esch384 hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 48-byte hash value. + * + * \sa esch_384_hash_init(), esch_384_hash_update() + */ +void esch_384_hash_finalize + (esch_384_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.c b/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.h b/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/api.h b/spix/Implementations/crypto_aead/spix128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/encrypt.c b/spix/Implementations/crypto_aead/spix128v1/rhys/encrypt.c new file mode 100644 index 0000000..facb770 --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spix.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 spix_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 spix_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.c b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.c new file mode 100644 index 0000000..69b4519 --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.c @@ -0,0 +1,408 @@ +/* + * 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 "internal-sliscp-light.h" + +/** + * \brief Performs one round of the Simeck-64 block cipher. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + */ +#define simeck64_round(x, y) \ + do { \ + (y) ^= (leftRotate5((x)) & (x)) ^ leftRotate1((x)) ^ \ + 0xFFFFFFFEU ^ (_rc & 1); \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 64-bit block with the 8 round version of Simeck-64. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck64_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck64_round(x, y); /* Round 1 */ \ + simeck64_round(y, x); /* Round 2 */ \ + simeck64_round(x, y); /* Round 3 */ \ + simeck64_round(y, x); /* Round 4 */ \ + simeck64_round(x, y); /* Round 5 */ \ + simeck64_round(y, x); /* Round 6 */ \ + simeck64_round(x, y); /* Round 7 */ \ + simeck64_round(y, x); /* Round 8 */ \ + } while (0) + +/* Helper macros for 48-bit left rotations */ +#define leftRotate5_48(x) (((x) << 5) | ((x) >> 19)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 23)) + +/** + * \brief Performs one round of the Simeck-48 block cipher. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + */ +#define simeck48_round(x, y) \ + do { \ + (y) ^= (leftRotate5_48((x)) & (x)) ^ leftRotate1_48((x)) ^ \ + 0x00FFFFFEU ^ (_rc & 1); \ + (y) &= 0x00FFFFFFU; \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 48-bit block with the 6 round version of Simeck-48. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck48_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck48_round(x, y); /* Round 1 */ \ + simeck48_round(y, x); /* Round 2 */ \ + simeck48_round(x, y); /* Round 3 */ \ + simeck48_round(y, x); /* Round 4 */ \ + simeck48_round(x, y); /* Round 5 */ \ + simeck48_round(y, x); /* Round 6 */ \ + } while (0) + +/* Interleaved rc0, rc1, sc0, and sc1 values for each round */ +static unsigned char const sliscp_light256_RC[18 * 4] = { + 0x0f, 0x47, 0x08, 0x64, 0x04, 0xb2, 0x86, 0x6b, + 0x43, 0xb5, 0xe2, 0x6f, 0xf1, 0x37, 0x89, 0x2c, + 0x44, 0x96, 0xe6, 0xdd, 0x73, 0xee, 0xca, 0x99, + 0xe5, 0x4c, 0x17, 0xea, 0x0b, 0xf5, 0x8e, 0x0f, + 0x47, 0x07, 0x64, 0x04, 0xb2, 0x82, 0x6b, 0x43, + 0xb5, 0xa1, 0x6f, 0xf1, 0x37, 0x78, 0x2c, 0x44, + 0x96, 0xa2, 0xdd, 0x73, 0xee, 0xb9, 0x99, 0xe5, + 0x4c, 0xf2, 0xea, 0x0b, 0xf5, 0x85, 0x0f, 0x47, + 0x07, 0x23, 0x04, 0xb2, 0x82, 0xd9, 0x43, 0xb5 +}; + +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 24); /* Assumes the block is pre-swapped */ + x4 = be_load_word32(block + 16); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 12); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 8, x2); + be_store_word32(block + 24, x3); /* Assumes the block is pre-swapped */ + be_store_word32(block + 16, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 12, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spix(unsigned char block[32]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 12); + t2 = le_load_word32(block + 24); + le_store_word32(block + 24, t1); + le_store_word32(block + 12, t2); +} + +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x3 = be_load_word32(block + 20); + x4 = be_load_word32(block + 8); + x5 = be_load_word32(block + 12); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 16, x2); /* Assumes the block is pre-swapped */ + be_store_word32(block + 20, x3); + be_store_word32(block + 8, x4); + be_store_word32(block + 12, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spoc(unsigned char block[32]) +{ + uint64_t t1, t2; + t1 = le_load_word64(block + 8); + t2 = le_load_word64(block + 16); + le_store_word64(block + 16, t1); + le_store_word64(block + 8, t2); +} + +/* Load a big-endian 24-bit word from a byte buffer */ +#define be_load_word24(ptr) \ + ((((uint32_t)((ptr)[0])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[2]))) + +/* Store a big-endian 24-bit word into a byte buffer */ +#define be_store_word24(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 16); \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)_x; \ + } while (0) + +void sliscp_light192_permute(unsigned char block[24]) +{ + /* Interleaved rc0, rc1, sc0, and sc1 values for each round */ + static unsigned char const RC[18 * 4] = { + 0x07, 0x27, 0x08, 0x29, 0x04, 0x34, 0x0c, 0x1d, + 0x06, 0x2e, 0x0a, 0x33, 0x25, 0x19, 0x2f, 0x2a, + 0x17, 0x35, 0x38, 0x1f, 0x1c, 0x0f, 0x24, 0x10, + 0x12, 0x08, 0x36, 0x18, 0x3b, 0x0c, 0x0d, 0x14, + 0x26, 0x0a, 0x2b, 0x1e, 0x15, 0x2f, 0x3e, 0x31, + 0x3f, 0x38, 0x01, 0x09, 0x20, 0x24, 0x21, 0x2d, + 0x30, 0x36, 0x11, 0x1b, 0x28, 0x0d, 0x39, 0x16, + 0x3c, 0x2b, 0x05, 0x3d, 0x22, 0x3e, 0x27, 0x03, + 0x13, 0x01, 0x34, 0x02, 0x1a, 0x21, 0x2e, 0x23 + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables. Each 24-bit block is + * placed into a separate 32-bit word which improves efficiency below */ + x0 = be_load_word24(block); + x1 = be_load_word24(block + 3); + x2 = be_load_word24(block + 6); + x3 = be_load_word24(block + 9); + x4 = be_load_word24(block + 12); + x5 = be_load_word24(block + 15); + x6 = be_load_word24(block + 18); + x7 = be_load_word24(block + 21); + + /* Perform all permutation rounds */ + for (round = 0; round < 18; ++round, rc += 4) { + /* Apply Simeck-48 to two of the 48-bit sub-blocks */ + simeck48_box(x2, x3, rc[0]); + simeck48_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0x00FFFFFFU; + x1 ^= 0x00FFFF00U ^ rc[2]; + x4 ^= 0x00FFFFFFU; + x5 ^= 0x00FFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word24(block, x0); + be_store_word24(block + 3, x1); + be_store_word24(block + 6, x2); + be_store_word24(block + 9, x3); + be_store_word24(block + 12, x4); + be_store_word24(block + 15, x5); + be_store_word24(block + 18, x6); + be_store_word24(block + 21, x7); +} + +void sliscp_light320_permute(unsigned char block[40]) +{ + /* Interleaved rc0, rc1, rc2, sc0, sc1, and sc2 values for each round */ + static unsigned char const RC[16 * 6] = { + 0x07, 0x53, 0x43, 0x50, 0x28, 0x14, 0x0a, 0x5d, + 0xe4, 0x5c, 0xae, 0x57, 0x9b, 0x49, 0x5e, 0x91, + 0x48, 0x24, 0xe0, 0x7f, 0xcc, 0x8d, 0xc6, 0x63, + 0xd1, 0xbe, 0x32, 0x53, 0xa9, 0x54, 0x1a, 0x1d, + 0x4e, 0x60, 0x30, 0x18, 0x22, 0x28, 0x75, 0x68, + 0x34, 0x9a, 0xf7, 0x6c, 0x25, 0xe1, 0x70, 0x38, + 0x62, 0x82, 0xfd, 0xf6, 0x7b, 0xbd, 0x96, 0x47, + 0xf9, 0x9d, 0xce, 0x67, 0x71, 0x6b, 0x76, 0x40, + 0x20, 0x10, 0xaa, 0x88, 0xa0, 0x4f, 0x27, 0x13, + 0x2b, 0xdc, 0xb0, 0xbe, 0x5f, 0x2f, 0xe9, 0x8b, + 0x09, 0x5b, 0xad, 0xd6, 0xcf, 0x59, 0x1e, 0xe9, + 0x74, 0xba, 0xb7, 0xc6, 0xad, 0x7f, 0x3f, 0x1f + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 12); + x4 = be_load_word32(block + 4); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + x8 = be_load_word32(block + 32); + x9 = be_load_word32(block + 36); + + /* Perform all permutation rounds */ + for (round = 0; round < 16; ++round, rc += 6) { + /* Apply Simeck-64 to three of the 64-bit sub-blocks */ + simeck64_box(x0, x1, rc[0]); + simeck64_box(x4, x5, rc[1]); + simeck64_box(x8, x9, rc[2]); + x6 ^= x8; + x7 ^= x9; + x2 ^= x4; + x3 ^= x5; + x8 ^= x0; + x9 ^= x1; + + /* Add step constants */ + x2 ^= 0xFFFFFFFFU; + x3 ^= 0xFFFFFF00U ^ rc[3]; + x6 ^= 0xFFFFFFFFU; + x7 ^= 0xFFFFFF00U ^ rc[4]; + x8 ^= 0xFFFFFFFFU; + x9 ^= 0xFFFFFF00U ^ rc[5]; + + /* Rotate the sub-blocks */ + t0 = x8; + t1 = x9; + x8 = x2; + x9 = x3; + x2 = x4; + x3 = x5; + x4 = x0; + x5 = x1; + x0 = x6; + x1 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 16, x1); /* Assumes the block is pre-swapped */ + be_store_word32(block + 8, x2); + be_store_word32(block + 12, x3); + be_store_word32(block + 4, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); + be_store_word32(block + 32, x8); + be_store_word32(block + 36, x9); +} + +void sliscp_light320_swap(unsigned char block[40]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 4); + t2 = le_load_word32(block + 16); + le_store_word32(block + 16, t1); + le_store_word32(block + 4, t2); +} diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.h b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.h new file mode 100644 index 0000000..fa6b9ba --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-sliscp-light.h @@ -0,0 +1,169 @@ +/* + * 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_SLISCP_LIGHT_H +#define LW_INTERNAL_SLISCP_LIGHT_H + +/** + * \file internal-sliscp-light.h + * \brief sLiSCP-light permutation + * + * There are three variants of sLiSCP-light in use in the NIST submissions: + * + * \li sLiSCP-light-256 with a 256-bit block size, used in SPIX and SpoC. + * \li sLiSCP-light-192 with a 192-bit block size, used in SpoC. + * \li sLiSCP-light-320 with a 320-bit block size, used in ACE. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/ace, + * https://uwaterloo.ca/communications-security-lab/lwc/spix, + * https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for sLiSCP-light-256. + */ +#define SLISCP_LIGHT256_STATE_SIZE 32 + +/** + * \brief Size of the state for sLiSCP-light-192. + */ +#define SLISCP_LIGHT192_STATE_SIZE 24 + +/** + * \brief Size of the state for sLiSCP-light-320. + */ +#define SLISCP_LIGHT320_STATE_SIZE 40 + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SPIX cipher. SPIX places the rate bytes at + * positions 8, 9, 10, 11, 24, 25, 26, and 27. + * + * This function assumes that bytes 24-27 have been pre-swapped with + * bytes 12-15 so that the rate portion of the state is contiguous. + * + * The sliscp_light256_swap_spix() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spix() + */ +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SPIX. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spix() + */ +void sliscp_light256_swap_spix(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SpoC-128 cipher. SpoC-128 interleaves the + * rate bytes and the mask bytes. This version assumes that the + * rate and mask are in contiguous bytes of the state. + * + * SpoC-128 absorbs bytes using the mask bytes of the state at offsets + * 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, and 31. + * It squeezes bytes using the rate bytes of the state at offsets + * 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, and 23. + * + * This function assumes that bytes 8-15 have been pre-swapped with 16-23 + * so that the rate and mask portions of the state are contiguous. + * + * The sliscp_light256_swap_spoc() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spoc() + */ +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SpoC-128. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spoc() + */ +void sliscp_light256_swap_spoc(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 192-bit block. + * + * \param block Points to the block to be permuted. + */ +void sliscp_light192_permute(unsigned char block[24]); + +/** + * \brief Performs the sLiSCP-light permutation on a 320-bit block. + * + * \param block Points to the block to be permuted. + * + * The ACE specification refers to this permutation as "ACE" but that + * can be confused with the name of the AEAD mode so we call this + * permutation "sLiSCP-light-320" instead. + * + * ACE absorbs and squeezes data at the rate bytes 0, 1, 2, 3, 16, 17, 18, 19. + * Efficiency can suffer because of the discontinuity in rate byte positions. + * + * To counteract this, we assume that the input to the permutation has been + * pre-swapped: bytes 4, 5, 6, 7 are swapped with bytes 16, 17, 18, 19 so + * that the rate is contiguous at the start of the state. + * + * The sliscp_light320_swap() function can be used to switch between the + * canonical order and the pre-swapped order. + * + * \sa sliscp_light320_swap() + */ +void sliscp_light320_permute(unsigned char block[40]); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 320-bit block. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light320_permute() + */ +void sliscp_light320_swap(unsigned char block[40]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/internal-util.h b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/spix.c b/spix/Implementations/crypto_aead/spix128v1/rhys/spix.c new file mode 100644 index 0000000..7fc8f6a --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/spix.c @@ -0,0 +1,211 @@ +/* + * 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 "spix.h" +#include "internal-sliscp-light.h" +#include "internal-util.h" +#include + +/** + * \brief Size of the state for the internal sLiSCP-light permutation. + */ +#define SPIX_STATE_SIZE SLISCP_LIGHT256_STATE_SIZE + +/** + * \brief Rate for absorbing data into the sLiSCP-light state and for + * squeezing data out again. + */ +#define SPIX_RATE 8 + +aead_cipher_t const spix_cipher = { + "SPIX", + SPIX_KEY_SIZE, + SPIX_NONCE_SIZE, + SPIX_TAG_SIZE, + AEAD_FLAG_NONE, + spix_aead_encrypt, + spix_aead_decrypt +}; + +/* Indices of where a rate byte is located in the state. We don't + * need this array any more because sliscp_light256_permute_spix() + * operates on byte-swapped states where the rate bytes are contiguous + * in the bytes 8 to 15 */ +/* +static unsigned char const spix_rate_posn[8] = { + 8, 9, 10, 11, 24, 25, 26, 27 +}; +*/ + +/** + * \brief Initializes the SPIX state. + * + * \param state sLiSCP-light-256 permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void spix_init + (unsigned char state[SPIX_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by interleaving the key and nonce */ + memcpy(state, npub, 8); + memcpy(state + 8, k, 8); + memcpy(state + 16, npub + 8, 8); + memcpy(state + 24, k + 8, 8); + sliscp_light256_swap_spix(state); + + /* Run the permutation to scramble the initial state */ + sliscp_light256_permute_spix(state, 18); + + /* Absorb the key in two further permutation operations */ + lw_xor_block(state + 8, k, 8); + sliscp_light256_permute_spix(state, 18); + lw_xor_block(state + 8, k + 8, 8); + sliscp_light256_permute_spix(state, 18); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= SPIX_RATE) { + lw_xor_block(state + 8, ad, SPIX_RATE); + state[SPIX_STATE_SIZE - 1] ^= 0x01; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + ad += SPIX_RATE; + adlen -= SPIX_RATE; + } + temp = (unsigned)adlen; + lw_xor_block(state + 8, ad, temp); + state[temp + 8] ^= 0x80; /* padding */ + state[SPIX_STATE_SIZE - 1] ^= 0x01; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + } +} + +/** + * \brief Finalizes the SPIX encryption or decryption operation. + * + * \param state sLiSCP-light-256 permutation state. + * \param k Points to the 128-bit key. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void spix_finalize + (unsigned char state[SPIX_STATE_SIZE], const unsigned char *k, + unsigned char *tag) +{ + /* Absorb the key into the state again */ + lw_xor_block(state + 8, k, 8); + sliscp_light256_permute_spix(state, 18); + lw_xor_block(state + 8, k + 8, 8); + sliscp_light256_permute_spix(state, 18); + + /* Copy out the authentication tag */ + sliscp_light256_swap_spix(state); + memcpy(tag, state + 8, 8); + memcpy(tag + 8, state + 24, 8); +} + +int spix_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) +{ + unsigned char state[SPIX_STATE_SIZE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPIX_TAG_SIZE; + + /* Initialize the SPIX state and absorb the associated data */ + spix_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= SPIX_RATE) { + lw_xor_block_2_dest(c, state + 8, m, SPIX_RATE); + state[SPIX_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + c += SPIX_RATE; + m += SPIX_RATE; + mlen -= SPIX_RATE; + } + temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state + 8, m, temp); + state[temp + 8] ^= 0x80; /* padding */ + state[SPIX_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + c += mlen; + + /* Generate the authentication tag */ + spix_finalize(state, k, c); + return 0; +} + +int spix_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) +{ + unsigned char state[SPIX_STATE_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPIX_TAG_SIZE) + return -1; + *mlen = clen - SPIX_TAG_SIZE; + + /* Initialize the SPIX state and absorb the associated data */ + spix_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPIX_TAG_SIZE; + while (clen >= SPIX_RATE) { + lw_xor_block_swap(m, state + 8, c, SPIX_RATE); + state[SPIX_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + c += SPIX_RATE; + m += SPIX_RATE; + clen -= SPIX_RATE; + } + temp = (unsigned)clen; + lw_xor_block_swap(m, state + 8, c, temp); + state[temp + 8] ^= 0x80; /* padding */ + state[SPIX_STATE_SIZE - 1] ^= 0x02; /* domain separation */ + sliscp_light256_permute_spix(state, 9); + c += clen; + + /* Finalize the SPIX state and compare against the authentication tag */ + spix_finalize(state, k, state); + return aead_check_tag(mtemp, *mlen, state, c, SPIX_TAG_SIZE); +} diff --git a/spix/Implementations/crypto_aead/spix128v1/rhys/spix.h b/spix/Implementations/crypto_aead/spix128v1/rhys/spix.h new file mode 100644 index 0000000..844c514 --- /dev/null +++ b/spix/Implementations/crypto_aead/spix128v1/rhys/spix.h @@ -0,0 +1,126 @@ +/* + * 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_SPIX_H +#define LWCRYPTO_SPIX_H + +#include "aead-common.h" + +/** + * \file spix.h + * \brief SPIX authenticated encryption algorithm. + * + * SPIX is an authenticated encryption algorithm with a 128-bit key, + * a 128-bit nonce, and a 128-bit tag. It uses the MonkeyDuplex + * construction on top of the 256-bit sLiSCP-light permutation. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/spix + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for SPIX. + */ +#define SPIX_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SPIX. + */ +#define SPIX_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SPIX. + */ +#define SPIX_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SPIX cipher. + */ +extern aead_cipher_t const spix_cipher; + +/** + * \brief Encrypts and authenticates a packet with SPIX. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spix_aead_decrypt() + */ +int spix_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); + +/** + * \brief Decrypts and authenticates a packet with SPIX. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spix_aead_encrypt() + */ +int spix_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.c b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.h b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/api.h b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/encrypt.c b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/encrypt.c new file mode 100644 index 0000000..6856b6f --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spoc.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 spoc_128_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 spoc_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.c b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.c new file mode 100644 index 0000000..69b4519 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.c @@ -0,0 +1,408 @@ +/* + * 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 "internal-sliscp-light.h" + +/** + * \brief Performs one round of the Simeck-64 block cipher. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + */ +#define simeck64_round(x, y) \ + do { \ + (y) ^= (leftRotate5((x)) & (x)) ^ leftRotate1((x)) ^ \ + 0xFFFFFFFEU ^ (_rc & 1); \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 64-bit block with the 8 round version of Simeck-64. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck64_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck64_round(x, y); /* Round 1 */ \ + simeck64_round(y, x); /* Round 2 */ \ + simeck64_round(x, y); /* Round 3 */ \ + simeck64_round(y, x); /* Round 4 */ \ + simeck64_round(x, y); /* Round 5 */ \ + simeck64_round(y, x); /* Round 6 */ \ + simeck64_round(x, y); /* Round 7 */ \ + simeck64_round(y, x); /* Round 8 */ \ + } while (0) + +/* Helper macros for 48-bit left rotations */ +#define leftRotate5_48(x) (((x) << 5) | ((x) >> 19)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 23)) + +/** + * \brief Performs one round of the Simeck-48 block cipher. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + */ +#define simeck48_round(x, y) \ + do { \ + (y) ^= (leftRotate5_48((x)) & (x)) ^ leftRotate1_48((x)) ^ \ + 0x00FFFFFEU ^ (_rc & 1); \ + (y) &= 0x00FFFFFFU; \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 48-bit block with the 6 round version of Simeck-48. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck48_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck48_round(x, y); /* Round 1 */ \ + simeck48_round(y, x); /* Round 2 */ \ + simeck48_round(x, y); /* Round 3 */ \ + simeck48_round(y, x); /* Round 4 */ \ + simeck48_round(x, y); /* Round 5 */ \ + simeck48_round(y, x); /* Round 6 */ \ + } while (0) + +/* Interleaved rc0, rc1, sc0, and sc1 values for each round */ +static unsigned char const sliscp_light256_RC[18 * 4] = { + 0x0f, 0x47, 0x08, 0x64, 0x04, 0xb2, 0x86, 0x6b, + 0x43, 0xb5, 0xe2, 0x6f, 0xf1, 0x37, 0x89, 0x2c, + 0x44, 0x96, 0xe6, 0xdd, 0x73, 0xee, 0xca, 0x99, + 0xe5, 0x4c, 0x17, 0xea, 0x0b, 0xf5, 0x8e, 0x0f, + 0x47, 0x07, 0x64, 0x04, 0xb2, 0x82, 0x6b, 0x43, + 0xb5, 0xa1, 0x6f, 0xf1, 0x37, 0x78, 0x2c, 0x44, + 0x96, 0xa2, 0xdd, 0x73, 0xee, 0xb9, 0x99, 0xe5, + 0x4c, 0xf2, 0xea, 0x0b, 0xf5, 0x85, 0x0f, 0x47, + 0x07, 0x23, 0x04, 0xb2, 0x82, 0xd9, 0x43, 0xb5 +}; + +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 24); /* Assumes the block is pre-swapped */ + x4 = be_load_word32(block + 16); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 12); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 8, x2); + be_store_word32(block + 24, x3); /* Assumes the block is pre-swapped */ + be_store_word32(block + 16, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 12, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spix(unsigned char block[32]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 12); + t2 = le_load_word32(block + 24); + le_store_word32(block + 24, t1); + le_store_word32(block + 12, t2); +} + +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x3 = be_load_word32(block + 20); + x4 = be_load_word32(block + 8); + x5 = be_load_word32(block + 12); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 16, x2); /* Assumes the block is pre-swapped */ + be_store_word32(block + 20, x3); + be_store_word32(block + 8, x4); + be_store_word32(block + 12, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spoc(unsigned char block[32]) +{ + uint64_t t1, t2; + t1 = le_load_word64(block + 8); + t2 = le_load_word64(block + 16); + le_store_word64(block + 16, t1); + le_store_word64(block + 8, t2); +} + +/* Load a big-endian 24-bit word from a byte buffer */ +#define be_load_word24(ptr) \ + ((((uint32_t)((ptr)[0])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[2]))) + +/* Store a big-endian 24-bit word into a byte buffer */ +#define be_store_word24(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 16); \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)_x; \ + } while (0) + +void sliscp_light192_permute(unsigned char block[24]) +{ + /* Interleaved rc0, rc1, sc0, and sc1 values for each round */ + static unsigned char const RC[18 * 4] = { + 0x07, 0x27, 0x08, 0x29, 0x04, 0x34, 0x0c, 0x1d, + 0x06, 0x2e, 0x0a, 0x33, 0x25, 0x19, 0x2f, 0x2a, + 0x17, 0x35, 0x38, 0x1f, 0x1c, 0x0f, 0x24, 0x10, + 0x12, 0x08, 0x36, 0x18, 0x3b, 0x0c, 0x0d, 0x14, + 0x26, 0x0a, 0x2b, 0x1e, 0x15, 0x2f, 0x3e, 0x31, + 0x3f, 0x38, 0x01, 0x09, 0x20, 0x24, 0x21, 0x2d, + 0x30, 0x36, 0x11, 0x1b, 0x28, 0x0d, 0x39, 0x16, + 0x3c, 0x2b, 0x05, 0x3d, 0x22, 0x3e, 0x27, 0x03, + 0x13, 0x01, 0x34, 0x02, 0x1a, 0x21, 0x2e, 0x23 + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables. Each 24-bit block is + * placed into a separate 32-bit word which improves efficiency below */ + x0 = be_load_word24(block); + x1 = be_load_word24(block + 3); + x2 = be_load_word24(block + 6); + x3 = be_load_word24(block + 9); + x4 = be_load_word24(block + 12); + x5 = be_load_word24(block + 15); + x6 = be_load_word24(block + 18); + x7 = be_load_word24(block + 21); + + /* Perform all permutation rounds */ + for (round = 0; round < 18; ++round, rc += 4) { + /* Apply Simeck-48 to two of the 48-bit sub-blocks */ + simeck48_box(x2, x3, rc[0]); + simeck48_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0x00FFFFFFU; + x1 ^= 0x00FFFF00U ^ rc[2]; + x4 ^= 0x00FFFFFFU; + x5 ^= 0x00FFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word24(block, x0); + be_store_word24(block + 3, x1); + be_store_word24(block + 6, x2); + be_store_word24(block + 9, x3); + be_store_word24(block + 12, x4); + be_store_word24(block + 15, x5); + be_store_word24(block + 18, x6); + be_store_word24(block + 21, x7); +} + +void sliscp_light320_permute(unsigned char block[40]) +{ + /* Interleaved rc0, rc1, rc2, sc0, sc1, and sc2 values for each round */ + static unsigned char const RC[16 * 6] = { + 0x07, 0x53, 0x43, 0x50, 0x28, 0x14, 0x0a, 0x5d, + 0xe4, 0x5c, 0xae, 0x57, 0x9b, 0x49, 0x5e, 0x91, + 0x48, 0x24, 0xe0, 0x7f, 0xcc, 0x8d, 0xc6, 0x63, + 0xd1, 0xbe, 0x32, 0x53, 0xa9, 0x54, 0x1a, 0x1d, + 0x4e, 0x60, 0x30, 0x18, 0x22, 0x28, 0x75, 0x68, + 0x34, 0x9a, 0xf7, 0x6c, 0x25, 0xe1, 0x70, 0x38, + 0x62, 0x82, 0xfd, 0xf6, 0x7b, 0xbd, 0x96, 0x47, + 0xf9, 0x9d, 0xce, 0x67, 0x71, 0x6b, 0x76, 0x40, + 0x20, 0x10, 0xaa, 0x88, 0xa0, 0x4f, 0x27, 0x13, + 0x2b, 0xdc, 0xb0, 0xbe, 0x5f, 0x2f, 0xe9, 0x8b, + 0x09, 0x5b, 0xad, 0xd6, 0xcf, 0x59, 0x1e, 0xe9, + 0x74, 0xba, 0xb7, 0xc6, 0xad, 0x7f, 0x3f, 0x1f + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 12); + x4 = be_load_word32(block + 4); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + x8 = be_load_word32(block + 32); + x9 = be_load_word32(block + 36); + + /* Perform all permutation rounds */ + for (round = 0; round < 16; ++round, rc += 6) { + /* Apply Simeck-64 to three of the 64-bit sub-blocks */ + simeck64_box(x0, x1, rc[0]); + simeck64_box(x4, x5, rc[1]); + simeck64_box(x8, x9, rc[2]); + x6 ^= x8; + x7 ^= x9; + x2 ^= x4; + x3 ^= x5; + x8 ^= x0; + x9 ^= x1; + + /* Add step constants */ + x2 ^= 0xFFFFFFFFU; + x3 ^= 0xFFFFFF00U ^ rc[3]; + x6 ^= 0xFFFFFFFFU; + x7 ^= 0xFFFFFF00U ^ rc[4]; + x8 ^= 0xFFFFFFFFU; + x9 ^= 0xFFFFFF00U ^ rc[5]; + + /* Rotate the sub-blocks */ + t0 = x8; + t1 = x9; + x8 = x2; + x9 = x3; + x2 = x4; + x3 = x5; + x4 = x0; + x5 = x1; + x0 = x6; + x1 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 16, x1); /* Assumes the block is pre-swapped */ + be_store_word32(block + 8, x2); + be_store_word32(block + 12, x3); + be_store_word32(block + 4, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); + be_store_word32(block + 32, x8); + be_store_word32(block + 36, x9); +} + +void sliscp_light320_swap(unsigned char block[40]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 4); + t2 = le_load_word32(block + 16); + le_store_word32(block + 16, t1); + le_store_word32(block + 4, t2); +} diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.h b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.h new file mode 100644 index 0000000..fa6b9ba --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-sliscp-light.h @@ -0,0 +1,169 @@ +/* + * 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_SLISCP_LIGHT_H +#define LW_INTERNAL_SLISCP_LIGHT_H + +/** + * \file internal-sliscp-light.h + * \brief sLiSCP-light permutation + * + * There are three variants of sLiSCP-light in use in the NIST submissions: + * + * \li sLiSCP-light-256 with a 256-bit block size, used in SPIX and SpoC. + * \li sLiSCP-light-192 with a 192-bit block size, used in SpoC. + * \li sLiSCP-light-320 with a 320-bit block size, used in ACE. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/ace, + * https://uwaterloo.ca/communications-security-lab/lwc/spix, + * https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for sLiSCP-light-256. + */ +#define SLISCP_LIGHT256_STATE_SIZE 32 + +/** + * \brief Size of the state for sLiSCP-light-192. + */ +#define SLISCP_LIGHT192_STATE_SIZE 24 + +/** + * \brief Size of the state for sLiSCP-light-320. + */ +#define SLISCP_LIGHT320_STATE_SIZE 40 + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SPIX cipher. SPIX places the rate bytes at + * positions 8, 9, 10, 11, 24, 25, 26, and 27. + * + * This function assumes that bytes 24-27 have been pre-swapped with + * bytes 12-15 so that the rate portion of the state is contiguous. + * + * The sliscp_light256_swap_spix() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spix() + */ +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SPIX. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spix() + */ +void sliscp_light256_swap_spix(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SpoC-128 cipher. SpoC-128 interleaves the + * rate bytes and the mask bytes. This version assumes that the + * rate and mask are in contiguous bytes of the state. + * + * SpoC-128 absorbs bytes using the mask bytes of the state at offsets + * 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, and 31. + * It squeezes bytes using the rate bytes of the state at offsets + * 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, and 23. + * + * This function assumes that bytes 8-15 have been pre-swapped with 16-23 + * so that the rate and mask portions of the state are contiguous. + * + * The sliscp_light256_swap_spoc() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spoc() + */ +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SpoC-128. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spoc() + */ +void sliscp_light256_swap_spoc(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 192-bit block. + * + * \param block Points to the block to be permuted. + */ +void sliscp_light192_permute(unsigned char block[24]); + +/** + * \brief Performs the sLiSCP-light permutation on a 320-bit block. + * + * \param block Points to the block to be permuted. + * + * The ACE specification refers to this permutation as "ACE" but that + * can be confused with the name of the AEAD mode so we call this + * permutation "sLiSCP-light-320" instead. + * + * ACE absorbs and squeezes data at the rate bytes 0, 1, 2, 3, 16, 17, 18, 19. + * Efficiency can suffer because of the discontinuity in rate byte positions. + * + * To counteract this, we assume that the input to the permutation has been + * pre-swapped: bytes 4, 5, 6, 7 are swapped with bytes 16, 17, 18, 19 so + * that the rate is contiguous at the start of the state. + * + * The sliscp_light320_swap() function can be used to switch between the + * canonical order and the pre-swapped order. + * + * \sa sliscp_light320_swap() + */ +void sliscp_light320_permute(unsigned char block[40]); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 320-bit block. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light320_permute() + */ +void sliscp_light320_swap(unsigned char block[40]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-util.h b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.c b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.c new file mode 100644 index 0000000..1af7d59 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.c @@ -0,0 +1,406 @@ +/* + * 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 "spoc.h" +#include "internal-sliscp-light.h" +#include "internal-util.h" +#include + +/** + * \brief Size of the state for the internal sLiSCP-light-256 permutation. + */ +#define SPOC_128_STATE_SIZE SLISCP_LIGHT256_STATE_SIZE + +/** + * \brief Rate for absorbing data into the sLiSCP-light-256 state and for + * squeezing data out again. + */ +#define SPOC_128_RATE 16 + +/** + * \brief Size of the state for the internal sLiSCP-light-192 permutation. + */ +#define SPOC_64_STATE_SIZE SLISCP_LIGHT192_STATE_SIZE + +/** + * \brief Rate for absorbing data into the sLiSCP-light-192 state and for + * squeezing data out again. + */ +#define SPOC_64_RATE 8 + +aead_cipher_t const spoc_128_cipher = { + "SpoC-128", + SPOC_KEY_SIZE, + SPOC_NONCE_SIZE, + SPOC_128_TAG_SIZE, + AEAD_FLAG_NONE, + spoc_128_aead_encrypt, + spoc_128_aead_decrypt +}; + +aead_cipher_t const spoc_64_cipher = { + "SpoC-64", + SPOC_KEY_SIZE, + SPOC_NONCE_SIZE, + SPOC_64_TAG_SIZE, + AEAD_FLAG_NONE, + spoc_64_aead_encrypt, + spoc_64_aead_decrypt +}; + +/* Indices of where a rate byte is located to help with padding */ +/* +static unsigned char const spoc_128_rate_posn[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23 +}; +static unsigned char const spoc_128_mask_posn[16] = { + 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31 +}; +*/ +static unsigned char const spoc_64_rate_posn[8] = { + 0, 1, 2, 3, 12, 13, 14, 15 +}; +static unsigned char const spoc_64_mask_posn[8] = { + 6, 7, 8, 9, 18, 19, 20, 21 +}; + +/** + * \brief Initializes the SpoC-128 state. + * + * \param state sLiSCP-light-256 permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void spoc_128_init + (unsigned char state[SPOC_128_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by combining the key and nonce */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, ad, SPOC_128_RATE); + state[0] ^= 0x20; /* domain separation */ + ad += SPOC_128_RATE; + adlen -= SPOC_128_RATE; + } + temp = (unsigned)adlen; + if (temp > 0) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, ad, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x30; /* domain separation */ + } + } +} + +/** + * \brief Initializes the SpoC-64 state. + * + * \param state sLiSCP-light-192 permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void spoc_64_init + (unsigned char state[SPOC_64_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by interleaving the key and nonce */ + memcpy(state, npub, 4); + state[4] = k[6]; + state[5] = k[7]; + memcpy(state + 6, k, 6); + memcpy(state + 12, npub + 4, 4); + state[16] = k[14]; + state[17] = k[15]; + memcpy(state + 18, k + 8, 6); + sliscp_light192_permute(state); + lw_xor_block(state + 6, npub + 8, 4); + lw_xor_block(state + 18, npub + 12, 4); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block(state + 6, ad, 4); + lw_xor_block(state + 18, ad + 4, 4); + state[0] ^= 0x20; /* domain separation */ + ad += SPOC_64_RATE; + adlen -= SPOC_64_RATE; + } + temp = (unsigned)adlen; + if (temp > 0) { + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + state[0] ^= 0x30; /* domain separation */ + while (temp > 0) { + --temp; + state[spoc_64_mask_posn[temp]] ^= ad[temp]; + } + } + } +} + +/** + * \brief Finalizes the SpoC-128 encryption or decryption operation. + * + * \param state sLiSCP-light-256 permutation state. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void spoc_128_finalize + (unsigned char state[SPOC_128_STATE_SIZE], unsigned char *tag) +{ + /* Pad and permute the state one more time */ + state[0] ^= 0x80; + sliscp_light256_permute_spoc(state, 18); + + /* Copy out the authentication tag */ + memcpy(tag, state + 16, 16); +} + +/** + * \brief Finalizes the SpoC-64 encryption or decryption operation. + * + * \param state sLiSCP-light-192 permutation state. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void spoc_64_finalize + (unsigned char state[SPOC_64_STATE_SIZE], unsigned char *tag) +{ + /* Pad and permute the state one more time */ + state[0] ^= 0x80; + sliscp_light192_permute(state); + + /* Copy out the authentication tag */ + memcpy(tag, state + 6, 4); + memcpy(tag + 4, state + 18, 4); +} + +int spoc_128_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) +{ + unsigned char state[SPOC_128_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOC_128_TAG_SIZE; + + /* Initialize the SpoC-128 state and absorb the associated data */ + spoc_128_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen != 0) { + while (mlen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, m, SPOC_128_RATE); + lw_xor_block_2_src(c, m, state, SPOC_128_RATE); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_128_RATE; + m += SPOC_128_RATE; + mlen -= SPOC_128_RATE; + } + if (mlen != 0) { + unsigned temp = (unsigned)mlen; + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, m, temp); + lw_xor_block_2_src(c, m, state, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x50; /* domain separation */ + c += mlen; + } + } + + /* Finalize and generate the authentication tag */ + spoc_128_finalize(state, c); + return 0; +} + +int spoc_128_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) +{ + unsigned char state[SPOC_128_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOC_128_TAG_SIZE) + return -1; + *mlen = clen - SPOC_128_TAG_SIZE; + + /* Initialize the Spoc-128 state and absorb the associated data */ + spoc_128_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOC_128_TAG_SIZE; + if (clen != 0) { + while (clen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block_2_src(m, c, state, SPOC_128_RATE); + lw_xor_block(state + 16, m, SPOC_128_RATE); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_128_RATE; + m += SPOC_128_RATE; + clen -= SPOC_128_RATE; + } + if (clen != 0) { + unsigned temp = (unsigned)clen; + sliscp_light256_permute_spoc(state, 18); + lw_xor_block_2_src(m, c, state, temp); + lw_xor_block(state + 16, m, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x50; /* domain separation */ + c += clen; + } + } + + /* Finalize and check the authentication tag */ + spoc_128_finalize(state, state); + return aead_check_tag(mtemp, *mlen, state, c, SPOC_128_TAG_SIZE); +} + +int spoc_64_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) +{ + unsigned char state[SPOC_64_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOC_64_TAG_SIZE; + + /* Initialize the SpoC-64 state and absorb the associated data */ + spoc_64_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen != 0) { + while (mlen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block(state + 6, m, 4); + lw_xor_block(state + 18, m + 4, 4); + lw_xor_block_2_src(c, m, state, 4); + lw_xor_block_2_src(c + 4, m + 4, state + 12, 4); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_64_RATE; + m += SPOC_64_RATE; + mlen -= SPOC_64_RATE; + } + if (mlen != 0) { + unsigned temp = (unsigned)mlen; + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + while (temp > 0) { + --temp; + unsigned char mbyte = m[temp]; + state[spoc_64_mask_posn[temp]] ^= mbyte; + c[temp] = mbyte ^ state[spoc_64_rate_posn[temp]]; + } + state[0] ^= 0x50; /* domain separation */ + c += mlen; + } + } + + /* Finalize and generate the authentication tag */ + spoc_64_finalize(state, c); + return 0; +} + +int spoc_64_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) +{ + unsigned char state[SPOC_64_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOC_64_TAG_SIZE) + return -1; + *mlen = clen - SPOC_64_TAG_SIZE; + + /* Initialize the Spoc-64 state and absorb the associated data */ + spoc_64_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOC_64_TAG_SIZE; + if (clen != 0) { + while (clen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block_2_src(m, c, state, 4); + lw_xor_block_2_src(m + 4, c + 4, state + 12, 4); + lw_xor_block(state + 6, m, 4); + lw_xor_block(state + 18, m + 4, 4); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_64_RATE; + m += SPOC_64_RATE; + clen -= SPOC_64_RATE; + } + if (clen != 0) { + unsigned temp = (unsigned)clen; + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + while (temp > 0) { + --temp; + unsigned char mbyte = c[temp] ^ state[spoc_64_rate_posn[temp]]; + state[spoc_64_mask_posn[temp]] ^= mbyte; + m[temp] = mbyte; + } + state[0] ^= 0x50; /* domain separation */ + c += clen; + } + } + + /* Finalize and check the authentication tag */ + spoc_64_finalize(state, state); + return aead_check_tag(mtemp, *mlen, state, c, SPOC_64_TAG_SIZE); +} diff --git a/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.h b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.h new file mode 100644 index 0000000..712c2d0 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc128sliscplight256v1/rhys/spoc.h @@ -0,0 +1,204 @@ +/* + * 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_SPOC_H +#define LWCRYPTO_SPOC_H + +#include "aead-common.h" + +/** + * \file spoc.h + * \brief SpoC authenticated encryption algorithm. + * + * SpoC is a family of authenticated encryption algorithms with two + * members, SpoC-128 and Spoc-64. The algorithms use a Beetle-like + * sponge construction built on top of the sLiSCP-light permutation. + * + * \li Spoc-128 has a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * It is built around the 256-bit version of the sLiSCP-light permutation. + * This is the primary member of the family. + * \li Spoc-64 has a 128-bit key, a 128-bit nonce, and a 64-bit tag. + * It is built around the 192-bit version of the sLiSCP-light permutation. + * + * Spoc-128 has good performance on small packets (16 bytes or less) + * on 32-bit embedded platforms. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SpoC variants. + */ +#define SPOC_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SpoC-128. + */ +#define SPOC_128_TAG_SIZE 16 + +/** + * \brief Size of the authentication tag for SpoC-64. + */ +#define SPOC_64_TAG_SIZE 8 + +/** + * \brief Size of the nonce for all SpoC variants. + */ +#define SPOC_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SpoC-128 cipher. + */ +extern aead_cipher_t const spoc_128_cipher; + +/** + * \brief Meta-information block for the SpoC-64 cipher. + */ +extern aead_cipher_t const spoc_64_cipher; + +/** + * \brief Encrypts and authenticates a packet with SpoC-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spoc_128_aead_decrypt() + */ +int spoc_128_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); + +/** + * \brief Decrypts and authenticates a packet with SpoC-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spoc_128_aead_encrypt() + */ +int spoc_128_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); + +/** + * \brief Encrypts and authenticates a packet with SpoC-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spoc_64_aead_decrypt() + */ +int spoc_64_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); + +/** + * \brief Decrypts and authenticates a packet with SpoC-64. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spoc_64_aead_encrypt() + */ +int spoc_64_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.c b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.h b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/api.h b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/api.h new file mode 100644 index 0000000..4bf8f5c --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/encrypt.c b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/encrypt.c new file mode 100644 index 0000000..f8dd710 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spoc.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 spoc_64_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 spoc_64_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.c b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.c new file mode 100644 index 0000000..69b4519 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.c @@ -0,0 +1,408 @@ +/* + * 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 "internal-sliscp-light.h" + +/** + * \brief Performs one round of the Simeck-64 block cipher. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + */ +#define simeck64_round(x, y) \ + do { \ + (y) ^= (leftRotate5((x)) & (x)) ^ leftRotate1((x)) ^ \ + 0xFFFFFFFEU ^ (_rc & 1); \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 64-bit block with the 8 round version of Simeck-64. + * + * \param x Left half of the 64-bit block. + * \param y Right half of the 64-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck64_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck64_round(x, y); /* Round 1 */ \ + simeck64_round(y, x); /* Round 2 */ \ + simeck64_round(x, y); /* Round 3 */ \ + simeck64_round(y, x); /* Round 4 */ \ + simeck64_round(x, y); /* Round 5 */ \ + simeck64_round(y, x); /* Round 6 */ \ + simeck64_round(x, y); /* Round 7 */ \ + simeck64_round(y, x); /* Round 8 */ \ + } while (0) + +/* Helper macros for 48-bit left rotations */ +#define leftRotate5_48(x) (((x) << 5) | ((x) >> 19)) +#define leftRotate1_48(x) (((x) << 1) | ((x) >> 23)) + +/** + * \brief Performs one round of the Simeck-48 block cipher. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + */ +#define simeck48_round(x, y) \ + do { \ + (y) ^= (leftRotate5_48((x)) & (x)) ^ leftRotate1_48((x)) ^ \ + 0x00FFFFFEU ^ (_rc & 1); \ + (y) &= 0x00FFFFFFU; \ + _rc >>= 1; \ + } while (0) + +/** + * \brief Encrypts a 48-bit block with the 6 round version of Simeck-48. + * + * \param x Left half of the 48-bit block. + * \param y Right half of the 48-bit block. + * \param rc Round constants for the 8 rounds, 1 bit per round. + * + * It is assumed that the two halves have already been converted from + * big-endian to host byte order before calling this function. The output + * halves will also be in host byte order. + */ +#define simeck48_box(x, y, rc) \ + do { \ + unsigned char _rc = (rc); \ + simeck48_round(x, y); /* Round 1 */ \ + simeck48_round(y, x); /* Round 2 */ \ + simeck48_round(x, y); /* Round 3 */ \ + simeck48_round(y, x); /* Round 4 */ \ + simeck48_round(x, y); /* Round 5 */ \ + simeck48_round(y, x); /* Round 6 */ \ + } while (0) + +/* Interleaved rc0, rc1, sc0, and sc1 values for each round */ +static unsigned char const sliscp_light256_RC[18 * 4] = { + 0x0f, 0x47, 0x08, 0x64, 0x04, 0xb2, 0x86, 0x6b, + 0x43, 0xb5, 0xe2, 0x6f, 0xf1, 0x37, 0x89, 0x2c, + 0x44, 0x96, 0xe6, 0xdd, 0x73, 0xee, 0xca, 0x99, + 0xe5, 0x4c, 0x17, 0xea, 0x0b, 0xf5, 0x8e, 0x0f, + 0x47, 0x07, 0x64, 0x04, 0xb2, 0x82, 0x6b, 0x43, + 0xb5, 0xa1, 0x6f, 0xf1, 0x37, 0x78, 0x2c, 0x44, + 0x96, 0xa2, 0xdd, 0x73, 0xee, 0xb9, 0x99, 0xe5, + 0x4c, 0xf2, 0xea, 0x0b, 0xf5, 0x85, 0x0f, 0x47, + 0x07, 0x23, 0x04, 0xb2, 0x82, 0xd9, 0x43, 0xb5 +}; + +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 24); /* Assumes the block is pre-swapped */ + x4 = be_load_word32(block + 16); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 12); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 8, x2); + be_store_word32(block + 24, x3); /* Assumes the block is pre-swapped */ + be_store_word32(block + 16, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 12, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spix(unsigned char block[32]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 12); + t2 = le_load_word32(block + 24); + le_store_word32(block + 24, t1); + le_store_word32(block + 12, t2); +} + +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds) +{ + const unsigned char *rc = sliscp_light256_RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 4); + x2 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x3 = be_load_word32(block + 20); + x4 = be_load_word32(block + 8); + x5 = be_load_word32(block + 12); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + + /* Perform all permutation rounds */ + for (; rounds > 0; --rounds, rc += 4) { + /* Apply Simeck-64 to two of the 64-bit sub-blocks */ + simeck64_box(x2, x3, rc[0]); + simeck64_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0xFFFFFFFFU; + x1 ^= 0xFFFFFF00U ^ rc[2]; + x4 ^= 0xFFFFFFFFU; + x5 ^= 0xFFFFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 4, x1); + be_store_word32(block + 16, x2); /* Assumes the block is pre-swapped */ + be_store_word32(block + 20, x3); + be_store_word32(block + 8, x4); + be_store_word32(block + 12, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); +} + +void sliscp_light256_swap_spoc(unsigned char block[32]) +{ + uint64_t t1, t2; + t1 = le_load_word64(block + 8); + t2 = le_load_word64(block + 16); + le_store_word64(block + 16, t1); + le_store_word64(block + 8, t2); +} + +/* Load a big-endian 24-bit word from a byte buffer */ +#define be_load_word24(ptr) \ + ((((uint32_t)((ptr)[0])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[2]))) + +/* Store a big-endian 24-bit word into a byte buffer */ +#define be_store_word24(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 16); \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)_x; \ + } while (0) + +void sliscp_light192_permute(unsigned char block[24]) +{ + /* Interleaved rc0, rc1, sc0, and sc1 values for each round */ + static unsigned char const RC[18 * 4] = { + 0x07, 0x27, 0x08, 0x29, 0x04, 0x34, 0x0c, 0x1d, + 0x06, 0x2e, 0x0a, 0x33, 0x25, 0x19, 0x2f, 0x2a, + 0x17, 0x35, 0x38, 0x1f, 0x1c, 0x0f, 0x24, 0x10, + 0x12, 0x08, 0x36, 0x18, 0x3b, 0x0c, 0x0d, 0x14, + 0x26, 0x0a, 0x2b, 0x1e, 0x15, 0x2f, 0x3e, 0x31, + 0x3f, 0x38, 0x01, 0x09, 0x20, 0x24, 0x21, 0x2d, + 0x30, 0x36, 0x11, 0x1b, 0x28, 0x0d, 0x39, 0x16, + 0x3c, 0x2b, 0x05, 0x3d, 0x22, 0x3e, 0x27, 0x03, + 0x13, 0x01, 0x34, 0x02, 0x1a, 0x21, 0x2e, 0x23 + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables. Each 24-bit block is + * placed into a separate 32-bit word which improves efficiency below */ + x0 = be_load_word24(block); + x1 = be_load_word24(block + 3); + x2 = be_load_word24(block + 6); + x3 = be_load_word24(block + 9); + x4 = be_load_word24(block + 12); + x5 = be_load_word24(block + 15); + x6 = be_load_word24(block + 18); + x7 = be_load_word24(block + 21); + + /* Perform all permutation rounds */ + for (round = 0; round < 18; ++round, rc += 4) { + /* Apply Simeck-48 to two of the 48-bit sub-blocks */ + simeck48_box(x2, x3, rc[0]); + simeck48_box(x6, x7, rc[1]); + + /* Add step constants */ + x0 ^= 0x00FFFFFFU; + x1 ^= 0x00FFFF00U ^ rc[2]; + x4 ^= 0x00FFFFFFU; + x5 ^= 0x00FFFF00U ^ rc[3]; + + /* Mix the sub-blocks */ + t0 = x0 ^ x2; + t1 = x1 ^ x3; + x0 = x2; + x1 = x3; + x2 = x4 ^ x6; + x3 = x5 ^ x7; + x4 = x6; + x5 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word24(block, x0); + be_store_word24(block + 3, x1); + be_store_word24(block + 6, x2); + be_store_word24(block + 9, x3); + be_store_word24(block + 12, x4); + be_store_word24(block + 15, x5); + be_store_word24(block + 18, x6); + be_store_word24(block + 21, x7); +} + +void sliscp_light320_permute(unsigned char block[40]) +{ + /* Interleaved rc0, rc1, rc2, sc0, sc1, and sc2 values for each round */ + static unsigned char const RC[16 * 6] = { + 0x07, 0x53, 0x43, 0x50, 0x28, 0x14, 0x0a, 0x5d, + 0xe4, 0x5c, 0xae, 0x57, 0x9b, 0x49, 0x5e, 0x91, + 0x48, 0x24, 0xe0, 0x7f, 0xcc, 0x8d, 0xc6, 0x63, + 0xd1, 0xbe, 0x32, 0x53, 0xa9, 0x54, 0x1a, 0x1d, + 0x4e, 0x60, 0x30, 0x18, 0x22, 0x28, 0x75, 0x68, + 0x34, 0x9a, 0xf7, 0x6c, 0x25, 0xe1, 0x70, 0x38, + 0x62, 0x82, 0xfd, 0xf6, 0x7b, 0xbd, 0x96, 0x47, + 0xf9, 0x9d, 0xce, 0x67, 0x71, 0x6b, 0x76, 0x40, + 0x20, 0x10, 0xaa, 0x88, 0xa0, 0x4f, 0x27, 0x13, + 0x2b, 0xdc, 0xb0, 0xbe, 0x5f, 0x2f, 0xe9, 0x8b, + 0x09, 0x5b, 0xad, 0xd6, 0xcf, 0x59, 0x1e, 0xe9, + 0x74, 0xba, 0xb7, 0xc6, 0xad, 0x7f, 0x3f, 0x1f + }; + const unsigned char *rc = RC; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + uint32_t t0, t1; + unsigned round; + + /* Load the block into local state variables */ + x0 = be_load_word32(block); + x1 = be_load_word32(block + 16); /* Assumes the block is pre-swapped */ + x2 = be_load_word32(block + 8); + x3 = be_load_word32(block + 12); + x4 = be_load_word32(block + 4); + x5 = be_load_word32(block + 20); + x6 = be_load_word32(block + 24); + x7 = be_load_word32(block + 28); + x8 = be_load_word32(block + 32); + x9 = be_load_word32(block + 36); + + /* Perform all permutation rounds */ + for (round = 0; round < 16; ++round, rc += 6) { + /* Apply Simeck-64 to three of the 64-bit sub-blocks */ + simeck64_box(x0, x1, rc[0]); + simeck64_box(x4, x5, rc[1]); + simeck64_box(x8, x9, rc[2]); + x6 ^= x8; + x7 ^= x9; + x2 ^= x4; + x3 ^= x5; + x8 ^= x0; + x9 ^= x1; + + /* Add step constants */ + x2 ^= 0xFFFFFFFFU; + x3 ^= 0xFFFFFF00U ^ rc[3]; + x6 ^= 0xFFFFFFFFU; + x7 ^= 0xFFFFFF00U ^ rc[4]; + x8 ^= 0xFFFFFFFFU; + x9 ^= 0xFFFFFF00U ^ rc[5]; + + /* Rotate the sub-blocks */ + t0 = x8; + t1 = x9; + x8 = x2; + x9 = x3; + x2 = x4; + x3 = x5; + x4 = x0; + x5 = x1; + x0 = x6; + x1 = x7; + x6 = t0; + x7 = t1; + } + + /* Store the state back into the block */ + be_store_word32(block, x0); + be_store_word32(block + 16, x1); /* Assumes the block is pre-swapped */ + be_store_word32(block + 8, x2); + be_store_word32(block + 12, x3); + be_store_word32(block + 4, x4); + be_store_word32(block + 20, x5); + be_store_word32(block + 24, x6); + be_store_word32(block + 28, x7); + be_store_word32(block + 32, x8); + be_store_word32(block + 36, x9); +} + +void sliscp_light320_swap(unsigned char block[40]) +{ + uint32_t t1, t2; + t1 = le_load_word32(block + 4); + t2 = le_load_word32(block + 16); + le_store_word32(block + 16, t1); + le_store_word32(block + 4, t2); +} diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.h b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.h new file mode 100644 index 0000000..fa6b9ba --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-sliscp-light.h @@ -0,0 +1,169 @@ +/* + * 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_SLISCP_LIGHT_H +#define LW_INTERNAL_SLISCP_LIGHT_H + +/** + * \file internal-sliscp-light.h + * \brief sLiSCP-light permutation + * + * There are three variants of sLiSCP-light in use in the NIST submissions: + * + * \li sLiSCP-light-256 with a 256-bit block size, used in SPIX and SpoC. + * \li sLiSCP-light-192 with a 192-bit block size, used in SpoC. + * \li sLiSCP-light-320 with a 320-bit block size, used in ACE. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/ace, + * https://uwaterloo.ca/communications-security-lab/lwc/spix, + * https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#include "internal-util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the state for sLiSCP-light-256. + */ +#define SLISCP_LIGHT256_STATE_SIZE 32 + +/** + * \brief Size of the state for sLiSCP-light-192. + */ +#define SLISCP_LIGHT192_STATE_SIZE 24 + +/** + * \brief Size of the state for sLiSCP-light-320. + */ +#define SLISCP_LIGHT320_STATE_SIZE 40 + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SPIX cipher. SPIX places the rate bytes at + * positions 8, 9, 10, 11, 24, 25, 26, and 27. + * + * This function assumes that bytes 24-27 have been pre-swapped with + * bytes 12-15 so that the rate portion of the state is contiguous. + * + * The sliscp_light256_swap_spix() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spix() + */ +void sliscp_light256_permute_spix(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SPIX. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spix() + */ +void sliscp_light256_swap_spix(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 256-bit block. + * + * \param block Points to the block to be permuted. + * \param rounds Number of rounds to be performed, usually 9 or 18. + * + * The bytes of the block are assumed to be rearranged to match the + * requirements of the SpoC-128 cipher. SpoC-128 interleaves the + * rate bytes and the mask bytes. This version assumes that the + * rate and mask are in contiguous bytes of the state. + * + * SpoC-128 absorbs bytes using the mask bytes of the state at offsets + * 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, and 31. + * It squeezes bytes using the rate bytes of the state at offsets + * 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, and 23. + * + * This function assumes that bytes 8-15 have been pre-swapped with 16-23 + * so that the rate and mask portions of the state are contiguous. + * + * The sliscp_light256_swap_spoc() function can be used to switch + * between the canonical order and the pre-swapped order. + * + * \sa sliscp_light256_swap_spoc() + */ +void sliscp_light256_permute_spoc(unsigned char block[32], unsigned rounds); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 256-bit block for SpoC-128. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light256_permute_spoc() + */ +void sliscp_light256_swap_spoc(unsigned char block[32]); + +/** + * \brief Performs the sLiSCP-light permutation on a 192-bit block. + * + * \param block Points to the block to be permuted. + */ +void sliscp_light192_permute(unsigned char block[24]); + +/** + * \brief Performs the sLiSCP-light permutation on a 320-bit block. + * + * \param block Points to the block to be permuted. + * + * The ACE specification refers to this permutation as "ACE" but that + * can be confused with the name of the AEAD mode so we call this + * permutation "sLiSCP-light-320" instead. + * + * ACE absorbs and squeezes data at the rate bytes 0, 1, 2, 3, 16, 17, 18, 19. + * Efficiency can suffer because of the discontinuity in rate byte positions. + * + * To counteract this, we assume that the input to the permutation has been + * pre-swapped: bytes 4, 5, 6, 7 are swapped with bytes 16, 17, 18, 19 so + * that the rate is contiguous at the start of the state. + * + * The sliscp_light320_swap() function can be used to switch between the + * canonical order and the pre-swapped order. + * + * \sa sliscp_light320_swap() + */ +void sliscp_light320_permute(unsigned char block[40]); + +/** + * \brief Swaps rate bytes in a sLiSCP-light 320-bit block. + * + * \param block Points to the block to be rate-swapped. + * + * \sa sliscp_light320_permute() + */ +void sliscp_light320_swap(unsigned char block[40]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-util.h b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.c b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.c new file mode 100644 index 0000000..1af7d59 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.c @@ -0,0 +1,406 @@ +/* + * 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 "spoc.h" +#include "internal-sliscp-light.h" +#include "internal-util.h" +#include + +/** + * \brief Size of the state for the internal sLiSCP-light-256 permutation. + */ +#define SPOC_128_STATE_SIZE SLISCP_LIGHT256_STATE_SIZE + +/** + * \brief Rate for absorbing data into the sLiSCP-light-256 state and for + * squeezing data out again. + */ +#define SPOC_128_RATE 16 + +/** + * \brief Size of the state for the internal sLiSCP-light-192 permutation. + */ +#define SPOC_64_STATE_SIZE SLISCP_LIGHT192_STATE_SIZE + +/** + * \brief Rate for absorbing data into the sLiSCP-light-192 state and for + * squeezing data out again. + */ +#define SPOC_64_RATE 8 + +aead_cipher_t const spoc_128_cipher = { + "SpoC-128", + SPOC_KEY_SIZE, + SPOC_NONCE_SIZE, + SPOC_128_TAG_SIZE, + AEAD_FLAG_NONE, + spoc_128_aead_encrypt, + spoc_128_aead_decrypt +}; + +aead_cipher_t const spoc_64_cipher = { + "SpoC-64", + SPOC_KEY_SIZE, + SPOC_NONCE_SIZE, + SPOC_64_TAG_SIZE, + AEAD_FLAG_NONE, + spoc_64_aead_encrypt, + spoc_64_aead_decrypt +}; + +/* Indices of where a rate byte is located to help with padding */ +/* +static unsigned char const spoc_128_rate_posn[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23 +}; +static unsigned char const spoc_128_mask_posn[16] = { + 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31 +}; +*/ +static unsigned char const spoc_64_rate_posn[8] = { + 0, 1, 2, 3, 12, 13, 14, 15 +}; +static unsigned char const spoc_64_mask_posn[8] = { + 6, 7, 8, 9, 18, 19, 20, 21 +}; + +/** + * \brief Initializes the SpoC-128 state. + * + * \param state sLiSCP-light-256 permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void spoc_128_init + (unsigned char state[SPOC_128_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by combining the key and nonce */ + memcpy(state, npub, 16); + memcpy(state + 16, k, 16); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, ad, SPOC_128_RATE); + state[0] ^= 0x20; /* domain separation */ + ad += SPOC_128_RATE; + adlen -= SPOC_128_RATE; + } + temp = (unsigned)adlen; + if (temp > 0) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, ad, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x30; /* domain separation */ + } + } +} + +/** + * \brief Initializes the SpoC-64 state. + * + * \param state sLiSCP-light-192 permutation state. + * \param k Points to the 128-bit key. + * \param npub Points to the 128-bit nonce. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void spoc_64_init + (unsigned char state[SPOC_64_STATE_SIZE], + const unsigned char *k, const unsigned char *npub, + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Initialize the state by interleaving the key and nonce */ + memcpy(state, npub, 4); + state[4] = k[6]; + state[5] = k[7]; + memcpy(state + 6, k, 6); + memcpy(state + 12, npub + 4, 4); + state[16] = k[14]; + state[17] = k[15]; + memcpy(state + 18, k + 8, 6); + sliscp_light192_permute(state); + lw_xor_block(state + 6, npub + 8, 4); + lw_xor_block(state + 18, npub + 12, 4); + + /* Absorb the associated data into the state */ + if (adlen != 0) { + while (adlen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block(state + 6, ad, 4); + lw_xor_block(state + 18, ad + 4, 4); + state[0] ^= 0x20; /* domain separation */ + ad += SPOC_64_RATE; + adlen -= SPOC_64_RATE; + } + temp = (unsigned)adlen; + if (temp > 0) { + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + state[0] ^= 0x30; /* domain separation */ + while (temp > 0) { + --temp; + state[spoc_64_mask_posn[temp]] ^= ad[temp]; + } + } + } +} + +/** + * \brief Finalizes the SpoC-128 encryption or decryption operation. + * + * \param state sLiSCP-light-256 permutation state. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void spoc_128_finalize + (unsigned char state[SPOC_128_STATE_SIZE], unsigned char *tag) +{ + /* Pad and permute the state one more time */ + state[0] ^= 0x80; + sliscp_light256_permute_spoc(state, 18); + + /* Copy out the authentication tag */ + memcpy(tag, state + 16, 16); +} + +/** + * \brief Finalizes the SpoC-64 encryption or decryption operation. + * + * \param state sLiSCP-light-192 permutation state. + * \param tag Points to the 16 byte buffer to receive the computed tag. + */ +static void spoc_64_finalize + (unsigned char state[SPOC_64_STATE_SIZE], unsigned char *tag) +{ + /* Pad and permute the state one more time */ + state[0] ^= 0x80; + sliscp_light192_permute(state); + + /* Copy out the authentication tag */ + memcpy(tag, state + 6, 4); + memcpy(tag + 4, state + 18, 4); +} + +int spoc_128_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) +{ + unsigned char state[SPOC_128_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOC_128_TAG_SIZE; + + /* Initialize the SpoC-128 state and absorb the associated data */ + spoc_128_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen != 0) { + while (mlen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, m, SPOC_128_RATE); + lw_xor_block_2_src(c, m, state, SPOC_128_RATE); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_128_RATE; + m += SPOC_128_RATE; + mlen -= SPOC_128_RATE; + } + if (mlen != 0) { + unsigned temp = (unsigned)mlen; + sliscp_light256_permute_spoc(state, 18); + lw_xor_block(state + 16, m, temp); + lw_xor_block_2_src(c, m, state, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x50; /* domain separation */ + c += mlen; + } + } + + /* Finalize and generate the authentication tag */ + spoc_128_finalize(state, c); + return 0; +} + +int spoc_128_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) +{ + unsigned char state[SPOC_128_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOC_128_TAG_SIZE) + return -1; + *mlen = clen - SPOC_128_TAG_SIZE; + + /* Initialize the Spoc-128 state and absorb the associated data */ + spoc_128_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOC_128_TAG_SIZE; + if (clen != 0) { + while (clen >= SPOC_128_RATE) { + sliscp_light256_permute_spoc(state, 18); + lw_xor_block_2_src(m, c, state, SPOC_128_RATE); + lw_xor_block(state + 16, m, SPOC_128_RATE); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_128_RATE; + m += SPOC_128_RATE; + clen -= SPOC_128_RATE; + } + if (clen != 0) { + unsigned temp = (unsigned)clen; + sliscp_light256_permute_spoc(state, 18); + lw_xor_block_2_src(m, c, state, temp); + lw_xor_block(state + 16, m, temp); + state[temp + 16] ^= 0x80; /* padding */ + state[0] ^= 0x50; /* domain separation */ + c += clen; + } + } + + /* Finalize and check the authentication tag */ + spoc_128_finalize(state, state); + return aead_check_tag(mtemp, *mlen, state, c, SPOC_128_TAG_SIZE); +} + +int spoc_64_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) +{ + unsigned char state[SPOC_64_STATE_SIZE]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOC_64_TAG_SIZE; + + /* Initialize the SpoC-64 state and absorb the associated data */ + spoc_64_init(state, k, npub, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen != 0) { + while (mlen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block(state + 6, m, 4); + lw_xor_block(state + 18, m + 4, 4); + lw_xor_block_2_src(c, m, state, 4); + lw_xor_block_2_src(c + 4, m + 4, state + 12, 4); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_64_RATE; + m += SPOC_64_RATE; + mlen -= SPOC_64_RATE; + } + if (mlen != 0) { + unsigned temp = (unsigned)mlen; + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + while (temp > 0) { + --temp; + unsigned char mbyte = m[temp]; + state[spoc_64_mask_posn[temp]] ^= mbyte; + c[temp] = mbyte ^ state[spoc_64_rate_posn[temp]]; + } + state[0] ^= 0x50; /* domain separation */ + c += mlen; + } + } + + /* Finalize and generate the authentication tag */ + spoc_64_finalize(state, c); + return 0; +} + +int spoc_64_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) +{ + unsigned char state[SPOC_64_STATE_SIZE]; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOC_64_TAG_SIZE) + return -1; + *mlen = clen - SPOC_64_TAG_SIZE; + + /* Initialize the Spoc-64 state and absorb the associated data */ + spoc_64_init(state, k, npub, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOC_64_TAG_SIZE; + if (clen != 0) { + while (clen >= SPOC_64_RATE) { + sliscp_light192_permute(state); + lw_xor_block_2_src(m, c, state, 4); + lw_xor_block_2_src(m + 4, c + 4, state + 12, 4); + lw_xor_block(state + 6, m, 4); + lw_xor_block(state + 18, m + 4, 4); + state[0] ^= 0x40; /* domain separation */ + c += SPOC_64_RATE; + m += SPOC_64_RATE; + clen -= SPOC_64_RATE; + } + if (clen != 0) { + unsigned temp = (unsigned)clen; + sliscp_light192_permute(state); + state[spoc_64_mask_posn[temp]] ^= 0x80; /* padding */ + while (temp > 0) { + --temp; + unsigned char mbyte = c[temp] ^ state[spoc_64_rate_posn[temp]]; + state[spoc_64_mask_posn[temp]] ^= mbyte; + m[temp] = mbyte; + } + state[0] ^= 0x50; /* domain separation */ + c += clen; + } + } + + /* Finalize and check the authentication tag */ + spoc_64_finalize(state, state); + return aead_check_tag(mtemp, *mlen, state, c, SPOC_64_TAG_SIZE); +} diff --git a/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.h b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.h new file mode 100644 index 0000000..712c2d0 --- /dev/null +++ b/spoc/Implementations/crypto_aead/spoc64sliscplight192v1/rhys/spoc.h @@ -0,0 +1,204 @@ +/* + * 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_SPOC_H +#define LWCRYPTO_SPOC_H + +#include "aead-common.h" + +/** + * \file spoc.h + * \brief SpoC authenticated encryption algorithm. + * + * SpoC is a family of authenticated encryption algorithms with two + * members, SpoC-128 and Spoc-64. The algorithms use a Beetle-like + * sponge construction built on top of the sLiSCP-light permutation. + * + * \li Spoc-128 has a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * It is built around the 256-bit version of the sLiSCP-light permutation. + * This is the primary member of the family. + * \li Spoc-64 has a 128-bit key, a 128-bit nonce, and a 64-bit tag. + * It is built around the 192-bit version of the sLiSCP-light permutation. + * + * Spoc-128 has good performance on small packets (16 bytes or less) + * on 32-bit embedded platforms. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/spoc + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SpoC variants. + */ +#define SPOC_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for SpoC-128. + */ +#define SPOC_128_TAG_SIZE 16 + +/** + * \brief Size of the authentication tag for SpoC-64. + */ +#define SPOC_64_TAG_SIZE 8 + +/** + * \brief Size of the nonce for all SpoC variants. + */ +#define SPOC_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SpoC-128 cipher. + */ +extern aead_cipher_t const spoc_128_cipher; + +/** + * \brief Meta-information block for the SpoC-64 cipher. + */ +extern aead_cipher_t const spoc_64_cipher; + +/** + * \brief Encrypts and authenticates a packet with SpoC-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spoc_128_aead_decrypt() + */ +int spoc_128_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); + +/** + * \brief Decrypts and authenticates a packet with SpoC-128. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spoc_128_aead_encrypt() + */ +int spoc_128_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); + +/** + * \brief Encrypts and authenticates a packet with SpoC-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spoc_64_aead_decrypt() + */ +int spoc_64_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); + +/** + * \brief Decrypts and authenticates a packet with SpoC-64. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spoc_64_aead_encrypt() + */ +int spoc_64_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.c b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.h b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/api.h b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/api.h new file mode 100644 index 0000000..fb1dab8 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/encrypt.c b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/encrypt.c new file mode 100644 index 0000000..df13efc --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spook.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 spook_128_384_mu_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 spook_128_384_mu_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.c b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.c new file mode 100644 index 0000000..0e19216 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.c @@ -0,0 +1,557 @@ +/* + * 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 "internal-spook.h" + +/** + * \brief Number of steps in the Clyde-128 block cipher. + * + * This is also the number of steps in the Shadow-512 and Shadow-384 + * permutations. + */ +#define CLYDE128_STEPS 6 + +/** + * \brief Round constants for the steps of Clyde-128. + */ +static uint8_t const rc[CLYDE128_STEPS][8] = { + {1, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1}, + {1, 1, 1, 0, 0, 1, 1, 1} +}; + +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t c, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); + s0 = le_load_word32((const unsigned char *)&(input[0])); + s1 = le_load_word32((const unsigned char *)&(input[1])); + s2 = le_load_word32((const unsigned char *)&(input[2])); + s3 = le_load_word32((const unsigned char *)&(input[3])); +#endif + + /* Add the initial tweakey to the state */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Perform the two rounds of this step */ + #define clyde128_sbox(s0, s1, s2, s3) \ + do { \ + c = (s0 & s1) ^ s2; \ + d = (s3 & s0) ^ s1; \ + s2 = (c & d) ^ s3; \ + s3 = (c & s3) ^ s0; \ + s0 = d; \ + s1 = c; \ + } while (0) + #define clyde128_lbox(x, y) \ + do { \ + c = x ^ rightRotate12(x); \ + d = y ^ rightRotate12(y); \ + c ^= rightRotate3(c); \ + d ^= rightRotate3(d); \ + x = c ^ leftRotate15(x); \ + y = d ^ leftRotate15(y); \ + c = x ^ leftRotate1(x); \ + d = y ^ leftRotate1(y); \ + x ^= leftRotate6(d); \ + y ^= leftRotate7(c); \ + x ^= rightRotate15(c); \ + y ^= rightRotate15(d); \ + } while (0) + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + + /* Update the tweakey on the fly and add it to the state */ + c = t2 ^ t0; + d = t3 ^ t1; + t2 = t0; + t3 = t1; + t0 = c; + t1 = d; + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + } + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t a, b, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); +#endif + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all rounds in pairs */ + for (step = CLYDE128_STEPS - 1; step >= 0; --step) { + /* Add the tweakey to the state and update the tweakey */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + a = t2 ^ t0; + b = t3 ^ t1; + t0 = t2; + t1 = t3; + t2 = a; + t3 = b; + + /* Perform the two rounds of this step */ + #define clyde128_inv_sbox(s0, s1, s2, s3) \ + do { \ + d = (s0 & s1) ^ s2; \ + a = (s1 & d) ^ s3; \ + b = (d & a) ^ s0; \ + s2 = (a & b) ^ s1; \ + s0 = a; \ + s1 = b; \ + s3 = d; \ + } while (0) + #define clyde128_inv_lbox(x, y) \ + do { \ + a = x ^ leftRotate7(x); \ + b = y ^ leftRotate7(y); \ + x ^= leftRotate1(a); \ + y ^= leftRotate1(b); \ + x ^= leftRotate12(a); \ + y ^= leftRotate12(b); \ + a = x ^ leftRotate1(x); \ + b = y ^ leftRotate1(y); \ + x ^= leftRotate6(b); \ + y ^= leftRotate7(a); \ + a ^= leftRotate15(x); \ + b ^= leftRotate15(y); \ + x = rightRotate16(a); \ + y = rightRotate16(b); \ + } while (0) + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + } + + /* Add the tweakey to the state one last time */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void shadow512(shadow512_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t s30, s31, s32, s33; + uint32_t c, d, w, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; + s30 = state->W[12]; + s31 = state->W[13]; + s32 = state->W[14]; + s33 = state->W[15]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); + s30 = le_load_word32(state->B + 48); + s31 = le_load_word32(state->B + 52); + s32 = le_load_word32(state->B + 56); + s33 = le_load_word32(state->B + 60); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the S-box and L-box to bundle 3 */ + clyde128_sbox(s30, s31, s32, s33); + clyde128_lbox(s30, s31); + clyde128_lbox(s32, s33); + s30 ^= rc[step][0] << 3; + s31 ^= rc[step][1] << 3; + s32 ^= rc[step][2] << 3; + s33 ^= rc[step][3] << 3; + clyde128_sbox(s30, s31, s32, s33); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow512_diffusion_layer(row) \ + do { \ + w = s0##row; \ + x = s1##row; \ + y = s2##row; \ + z = s3##row; \ + c = w ^ x; \ + d = y ^ z; \ + s0##row = x ^ d; \ + s1##row = w ^ d; \ + s2##row = c ^ z; \ + s3##row = c ^ y; \ + } while (0) + shadow512_diffusion_layer(0); + shadow512_diffusion_layer(1); + shadow512_diffusion_layer(2); + shadow512_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + s30 ^= rc[step][4] << 3; + s31 ^= rc[step][5] << 3; + s32 ^= rc[step][6] << 3; + s33 ^= rc[step][7] << 3; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; + state->W[12] = s30; + state->W[13] = s31; + state->W[14] = s32; + state->W[15] = s33; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); + le_store_word32(state->B + 48, s30); + le_store_word32(state->B + 52, s31); + le_store_word32(state->B + 56, s32); + le_store_word32(state->B + 60, s33); +#endif +} + +void shadow384(shadow384_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t c, d, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow384_diffusion_layer(row) \ + do { \ + x = s0##row; \ + y = s1##row; \ + z = s2##row; \ + s0##row = x ^ y ^ z; \ + s1##row = x ^ z; \ + s2##row = x ^ y; \ + } while (0) + shadow384_diffusion_layer(0); + shadow384_diffusion_layer(1); + shadow384_diffusion_layer(2); + shadow384_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); +#endif +} diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.h b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.h new file mode 100644 index 0000000..b08ce80 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-spook.h @@ -0,0 +1,146 @@ +/* + * 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_SPOOK_H +#define LW_INTERNAL_SPOOK_H + +#include "internal-util.h" + +/** + * \file internal-spook.h + * \brief Internal implementation details of the Spook AEAD mode. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the block for the Clyde-128 block cipher. + */ +#define CLYDE128_BLOCK_SIZE 16 + +/** + * \brief Size of the key for the Clyde-128 block cipher. + */ +#define CLYDE128_KEY_SIZE 16 + +/** + * \brief Size of the tweak for the Clyde-128 block cipher. + */ +#define CLYDE128_TWEAK_SIZE 16 + +/** + * \brief Size of the state for Shadow-512. + */ +#define SHADOW512_STATE_SIZE 64 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-512 state. + */ +#define SHADOW512_RATE 32 + +/** + * \brief Size of the state for Shadow-384. + */ +#define SHADOW384_STATE_SIZE 48 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-384 state. + */ +#define SHADOW384_RATE 16 + +/** + * \brief Internal state of the Shadow-512 permutation. + */ +typedef union +{ + uint32_t W[SHADOW512_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW512_STATE_SIZE]; /**< Bytes of the state */ + +} shadow512_state_t; + +/** + * \brief Internal state of the Shadow-384 permutation. + */ +typedef union +{ + uint32_t W[SHADOW384_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW384_STATE_SIZE]; /**< Bytes of the state */ + +} shadow384_state_t; + +/** + * \brief Encrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to encrypt with. + * \param tweak Points to the tweak to encrypt with. + * \param output Output buffer for the ciphertext. + * \param input Input buffer for the plaintext. + * + * \sa clyde128_decrypt() + */ +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); + +/** + * \brief Decrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to decrypt with. + * \param tweak Points to the tweak to decrypt with. + * \param output Output buffer for the plaintext. + * \param input Input buffer for the ciphertext. + * + * \sa clyde128_encrypt() + */ +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]); + +/** + * \brief Performs the Shadow-512 permutation on a state. + * + * \param state The Shadow-512 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow384() + */ +void shadow512(shadow512_state_t *state); + +/** + * \brief Performs the Shadow-384 permutation on a state. + * + * \param state The Shadow-384 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow512() + */ +void shadow384(shadow384_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-util.h b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.c b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.c new file mode 100644 index 0000000..d075b33 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.c @@ -0,0 +1,552 @@ +/* + * 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 "spook.h" +#include "internal-spook.h" +#include "internal-util.h" +#include + +aead_cipher_t const spook_128_512_su_cipher = { + "Spook-128-512-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_su_aead_encrypt, + spook_128_512_su_aead_decrypt +}; + +aead_cipher_t const spook_128_384_su_cipher = { + "Spook-128-384-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_su_aead_encrypt, + spook_128_384_su_aead_decrypt +}; + +aead_cipher_t const spook_128_512_mu_cipher = { + "Spook-128-512-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_mu_aead_encrypt, + spook_128_512_mu_aead_decrypt +}; + +aead_cipher_t const spook_128_384_mu_cipher = { + "Spook-128-384-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_mu_aead_encrypt, + spook_128_384_mu_aead_decrypt +}; + +/** + * \brief Initializes the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_512_init + (shadow512_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW512_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 12, state->W + 4); + shadow512(state); +} + +/** + * \brief Initializes the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_384_init + (shadow384_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW384_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 8, state->W + 4); + shadow384(state); +} + +/** + * \brief Absorbs associated data into the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_512_absorb + (shadow512_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW512_RATE) { + lw_xor_block(state->B, ad, SHADOW512_RATE); + shadow512(state); + ad += SHADOW512_RATE; + adlen -= SHADOW512_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Absorbs associated data into the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_384_absorb + (shadow384_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW384_RATE) { + lw_xor_block(state->B, ad, SHADOW384_RATE); + shadow384(state); + ad += SHADOW384_RATE; + adlen -= SHADOW384_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_512_encrypt + (shadow512_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (mlen >= SHADOW512_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + mlen -= SHADOW512_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_384_encrypt + (shadow384_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (mlen >= SHADOW384_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + mlen -= SHADOW384_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_512_decrypt + (shadow512_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (clen >= SHADOW512_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + clen -= SHADOW512_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_384_decrypt + (shadow384_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (clen >= SHADOW384_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + clen -= SHADOW384_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} diff --git a/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.h b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.h new file mode 100644 index 0000000..68b6a25 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu384v1/rhys/spook.h @@ -0,0 +1,344 @@ +/* + * 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_SPOOK_H +#define LWCRYPTO_SPOOK_H + +#include "aead-common.h" + +/** + * \file spook.h + * \brief Spook authenticated encryption algorithm. + * + * Spook is a family of authenticated encryption algorithms that are + * built around a tweakable block cipher and a permutation. If the + * tweakable block cipher is implemented as a masked block cipher, + * then Spook provides protection against power analysis side channels. + * + * There are four members in the Spook family: + * + * \li Spook-128-512-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 512-bit permutation. This is the primary + * member of the family. + * \li Spook-128-384-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 384-bit permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 512-bit + * permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 384-bit + * permutation. + * + * In this library, the "mu" (multi-user) variants combine the 128-bit key + * and the 128-bit public tweak into a single 256-bit key value. + * Applications can either view this as a cipher with a 256-bit key, + * or they can split the key value into secret and public halves. + * Even with the use of 256-bit keys, Spook only has 128-bit security. + * + * References: https://www.spook.dev/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for the single-user version of Spook. + */ +#define SPOOK_SU_KEY_SIZE 16 + +/** + * \brief Size of the key for the multi-user version of Spook. + */ +#define SPOOK_MU_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all Spook family members. + */ +#define SPOOK_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all Spook family members. + */ +#define SPOOK_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the Spook-128-512-su cipher. + */ +extern aead_cipher_t const spook_128_512_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-su cipher. + */ +extern aead_cipher_t const spook_128_384_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-512-mu cipher. + */ +extern aead_cipher_t const spook_128_512_mu_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-mu cipher. + */ +extern aead_cipher_t const spook_128_384_mu_cipher; + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_su_aead_decrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_512_su_aead_encrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_su_aead_decrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_384_su_aead_encrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_mu_aead_decrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_512_mu_aead_encrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_mu_aead_decrypt() + */ +int spook_128_384_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_384_mu_aead_encrypt() + */ +int spook_128_384_mu_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.c b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.h b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/api.h b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/api.h new file mode 100644 index 0000000..fb1dab8 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/encrypt.c b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/encrypt.c new file mode 100644 index 0000000..52c6ec8 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spook.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 spook_128_512_mu_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 spook_128_512_mu_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.c b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.c new file mode 100644 index 0000000..0e19216 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.c @@ -0,0 +1,557 @@ +/* + * 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 "internal-spook.h" + +/** + * \brief Number of steps in the Clyde-128 block cipher. + * + * This is also the number of steps in the Shadow-512 and Shadow-384 + * permutations. + */ +#define CLYDE128_STEPS 6 + +/** + * \brief Round constants for the steps of Clyde-128. + */ +static uint8_t const rc[CLYDE128_STEPS][8] = { + {1, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1}, + {1, 1, 1, 0, 0, 1, 1, 1} +}; + +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t c, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); + s0 = le_load_word32((const unsigned char *)&(input[0])); + s1 = le_load_word32((const unsigned char *)&(input[1])); + s2 = le_load_word32((const unsigned char *)&(input[2])); + s3 = le_load_word32((const unsigned char *)&(input[3])); +#endif + + /* Add the initial tweakey to the state */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Perform the two rounds of this step */ + #define clyde128_sbox(s0, s1, s2, s3) \ + do { \ + c = (s0 & s1) ^ s2; \ + d = (s3 & s0) ^ s1; \ + s2 = (c & d) ^ s3; \ + s3 = (c & s3) ^ s0; \ + s0 = d; \ + s1 = c; \ + } while (0) + #define clyde128_lbox(x, y) \ + do { \ + c = x ^ rightRotate12(x); \ + d = y ^ rightRotate12(y); \ + c ^= rightRotate3(c); \ + d ^= rightRotate3(d); \ + x = c ^ leftRotate15(x); \ + y = d ^ leftRotate15(y); \ + c = x ^ leftRotate1(x); \ + d = y ^ leftRotate1(y); \ + x ^= leftRotate6(d); \ + y ^= leftRotate7(c); \ + x ^= rightRotate15(c); \ + y ^= rightRotate15(d); \ + } while (0) + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + + /* Update the tweakey on the fly and add it to the state */ + c = t2 ^ t0; + d = t3 ^ t1; + t2 = t0; + t3 = t1; + t0 = c; + t1 = d; + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + } + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t a, b, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); +#endif + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all rounds in pairs */ + for (step = CLYDE128_STEPS - 1; step >= 0; --step) { + /* Add the tweakey to the state and update the tweakey */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + a = t2 ^ t0; + b = t3 ^ t1; + t0 = t2; + t1 = t3; + t2 = a; + t3 = b; + + /* Perform the two rounds of this step */ + #define clyde128_inv_sbox(s0, s1, s2, s3) \ + do { \ + d = (s0 & s1) ^ s2; \ + a = (s1 & d) ^ s3; \ + b = (d & a) ^ s0; \ + s2 = (a & b) ^ s1; \ + s0 = a; \ + s1 = b; \ + s3 = d; \ + } while (0) + #define clyde128_inv_lbox(x, y) \ + do { \ + a = x ^ leftRotate7(x); \ + b = y ^ leftRotate7(y); \ + x ^= leftRotate1(a); \ + y ^= leftRotate1(b); \ + x ^= leftRotate12(a); \ + y ^= leftRotate12(b); \ + a = x ^ leftRotate1(x); \ + b = y ^ leftRotate1(y); \ + x ^= leftRotate6(b); \ + y ^= leftRotate7(a); \ + a ^= leftRotate15(x); \ + b ^= leftRotate15(y); \ + x = rightRotate16(a); \ + y = rightRotate16(b); \ + } while (0) + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + } + + /* Add the tweakey to the state one last time */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void shadow512(shadow512_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t s30, s31, s32, s33; + uint32_t c, d, w, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; + s30 = state->W[12]; + s31 = state->W[13]; + s32 = state->W[14]; + s33 = state->W[15]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); + s30 = le_load_word32(state->B + 48); + s31 = le_load_word32(state->B + 52); + s32 = le_load_word32(state->B + 56); + s33 = le_load_word32(state->B + 60); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the S-box and L-box to bundle 3 */ + clyde128_sbox(s30, s31, s32, s33); + clyde128_lbox(s30, s31); + clyde128_lbox(s32, s33); + s30 ^= rc[step][0] << 3; + s31 ^= rc[step][1] << 3; + s32 ^= rc[step][2] << 3; + s33 ^= rc[step][3] << 3; + clyde128_sbox(s30, s31, s32, s33); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow512_diffusion_layer(row) \ + do { \ + w = s0##row; \ + x = s1##row; \ + y = s2##row; \ + z = s3##row; \ + c = w ^ x; \ + d = y ^ z; \ + s0##row = x ^ d; \ + s1##row = w ^ d; \ + s2##row = c ^ z; \ + s3##row = c ^ y; \ + } while (0) + shadow512_diffusion_layer(0); + shadow512_diffusion_layer(1); + shadow512_diffusion_layer(2); + shadow512_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + s30 ^= rc[step][4] << 3; + s31 ^= rc[step][5] << 3; + s32 ^= rc[step][6] << 3; + s33 ^= rc[step][7] << 3; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; + state->W[12] = s30; + state->W[13] = s31; + state->W[14] = s32; + state->W[15] = s33; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); + le_store_word32(state->B + 48, s30); + le_store_word32(state->B + 52, s31); + le_store_word32(state->B + 56, s32); + le_store_word32(state->B + 60, s33); +#endif +} + +void shadow384(shadow384_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t c, d, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow384_diffusion_layer(row) \ + do { \ + x = s0##row; \ + y = s1##row; \ + z = s2##row; \ + s0##row = x ^ y ^ z; \ + s1##row = x ^ z; \ + s2##row = x ^ y; \ + } while (0) + shadow384_diffusion_layer(0); + shadow384_diffusion_layer(1); + shadow384_diffusion_layer(2); + shadow384_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); +#endif +} diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.h b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.h new file mode 100644 index 0000000..b08ce80 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-spook.h @@ -0,0 +1,146 @@ +/* + * 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_SPOOK_H +#define LW_INTERNAL_SPOOK_H + +#include "internal-util.h" + +/** + * \file internal-spook.h + * \brief Internal implementation details of the Spook AEAD mode. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the block for the Clyde-128 block cipher. + */ +#define CLYDE128_BLOCK_SIZE 16 + +/** + * \brief Size of the key for the Clyde-128 block cipher. + */ +#define CLYDE128_KEY_SIZE 16 + +/** + * \brief Size of the tweak for the Clyde-128 block cipher. + */ +#define CLYDE128_TWEAK_SIZE 16 + +/** + * \brief Size of the state for Shadow-512. + */ +#define SHADOW512_STATE_SIZE 64 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-512 state. + */ +#define SHADOW512_RATE 32 + +/** + * \brief Size of the state for Shadow-384. + */ +#define SHADOW384_STATE_SIZE 48 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-384 state. + */ +#define SHADOW384_RATE 16 + +/** + * \brief Internal state of the Shadow-512 permutation. + */ +typedef union +{ + uint32_t W[SHADOW512_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW512_STATE_SIZE]; /**< Bytes of the state */ + +} shadow512_state_t; + +/** + * \brief Internal state of the Shadow-384 permutation. + */ +typedef union +{ + uint32_t W[SHADOW384_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW384_STATE_SIZE]; /**< Bytes of the state */ + +} shadow384_state_t; + +/** + * \brief Encrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to encrypt with. + * \param tweak Points to the tweak to encrypt with. + * \param output Output buffer for the ciphertext. + * \param input Input buffer for the plaintext. + * + * \sa clyde128_decrypt() + */ +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); + +/** + * \brief Decrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to decrypt with. + * \param tweak Points to the tweak to decrypt with. + * \param output Output buffer for the plaintext. + * \param input Input buffer for the ciphertext. + * + * \sa clyde128_encrypt() + */ +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]); + +/** + * \brief Performs the Shadow-512 permutation on a state. + * + * \param state The Shadow-512 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow384() + */ +void shadow512(shadow512_state_t *state); + +/** + * \brief Performs the Shadow-384 permutation on a state. + * + * \param state The Shadow-384 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow512() + */ +void shadow384(shadow384_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-util.h b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.c b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.c new file mode 100644 index 0000000..d075b33 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.c @@ -0,0 +1,552 @@ +/* + * 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 "spook.h" +#include "internal-spook.h" +#include "internal-util.h" +#include + +aead_cipher_t const spook_128_512_su_cipher = { + "Spook-128-512-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_su_aead_encrypt, + spook_128_512_su_aead_decrypt +}; + +aead_cipher_t const spook_128_384_su_cipher = { + "Spook-128-384-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_su_aead_encrypt, + spook_128_384_su_aead_decrypt +}; + +aead_cipher_t const spook_128_512_mu_cipher = { + "Spook-128-512-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_mu_aead_encrypt, + spook_128_512_mu_aead_decrypt +}; + +aead_cipher_t const spook_128_384_mu_cipher = { + "Spook-128-384-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_mu_aead_encrypt, + spook_128_384_mu_aead_decrypt +}; + +/** + * \brief Initializes the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_512_init + (shadow512_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW512_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 12, state->W + 4); + shadow512(state); +} + +/** + * \brief Initializes the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_384_init + (shadow384_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW384_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 8, state->W + 4); + shadow384(state); +} + +/** + * \brief Absorbs associated data into the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_512_absorb + (shadow512_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW512_RATE) { + lw_xor_block(state->B, ad, SHADOW512_RATE); + shadow512(state); + ad += SHADOW512_RATE; + adlen -= SHADOW512_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Absorbs associated data into the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_384_absorb + (shadow384_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW384_RATE) { + lw_xor_block(state->B, ad, SHADOW384_RATE); + shadow384(state); + ad += SHADOW384_RATE; + adlen -= SHADOW384_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_512_encrypt + (shadow512_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (mlen >= SHADOW512_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + mlen -= SHADOW512_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_384_encrypt + (shadow384_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (mlen >= SHADOW384_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + mlen -= SHADOW384_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_512_decrypt + (shadow512_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (clen >= SHADOW512_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + clen -= SHADOW512_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_384_decrypt + (shadow384_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (clen >= SHADOW384_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + clen -= SHADOW384_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} diff --git a/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.h b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.h new file mode 100644 index 0000000..68b6a25 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128mu512v1/rhys/spook.h @@ -0,0 +1,344 @@ +/* + * 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_SPOOK_H +#define LWCRYPTO_SPOOK_H + +#include "aead-common.h" + +/** + * \file spook.h + * \brief Spook authenticated encryption algorithm. + * + * Spook is a family of authenticated encryption algorithms that are + * built around a tweakable block cipher and a permutation. If the + * tweakable block cipher is implemented as a masked block cipher, + * then Spook provides protection against power analysis side channels. + * + * There are four members in the Spook family: + * + * \li Spook-128-512-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 512-bit permutation. This is the primary + * member of the family. + * \li Spook-128-384-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 384-bit permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 512-bit + * permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 384-bit + * permutation. + * + * In this library, the "mu" (multi-user) variants combine the 128-bit key + * and the 128-bit public tweak into a single 256-bit key value. + * Applications can either view this as a cipher with a 256-bit key, + * or they can split the key value into secret and public halves. + * Even with the use of 256-bit keys, Spook only has 128-bit security. + * + * References: https://www.spook.dev/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for the single-user version of Spook. + */ +#define SPOOK_SU_KEY_SIZE 16 + +/** + * \brief Size of the key for the multi-user version of Spook. + */ +#define SPOOK_MU_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all Spook family members. + */ +#define SPOOK_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all Spook family members. + */ +#define SPOOK_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the Spook-128-512-su cipher. + */ +extern aead_cipher_t const spook_128_512_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-su cipher. + */ +extern aead_cipher_t const spook_128_384_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-512-mu cipher. + */ +extern aead_cipher_t const spook_128_512_mu_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-mu cipher. + */ +extern aead_cipher_t const spook_128_384_mu_cipher; + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_su_aead_decrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_512_su_aead_encrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_su_aead_decrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_384_su_aead_encrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_mu_aead_decrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_512_mu_aead_encrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_mu_aead_decrypt() + */ +int spook_128_384_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_384_mu_aead_encrypt() + */ +int spook_128_384_mu_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.c b/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.h b/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/api.h b/spook/Implementations/crypto_aead/spook128su384v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/encrypt.c b/spook/Implementations/crypto_aead/spook128su384v1/rhys/encrypt.c new file mode 100644 index 0000000..e61a44a --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spook.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 spook_128_384_su_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 spook_128_384_su_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.c b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.c new file mode 100644 index 0000000..0e19216 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.c @@ -0,0 +1,557 @@ +/* + * 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 "internal-spook.h" + +/** + * \brief Number of steps in the Clyde-128 block cipher. + * + * This is also the number of steps in the Shadow-512 and Shadow-384 + * permutations. + */ +#define CLYDE128_STEPS 6 + +/** + * \brief Round constants for the steps of Clyde-128. + */ +static uint8_t const rc[CLYDE128_STEPS][8] = { + {1, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1}, + {1, 1, 1, 0, 0, 1, 1, 1} +}; + +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t c, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); + s0 = le_load_word32((const unsigned char *)&(input[0])); + s1 = le_load_word32((const unsigned char *)&(input[1])); + s2 = le_load_word32((const unsigned char *)&(input[2])); + s3 = le_load_word32((const unsigned char *)&(input[3])); +#endif + + /* Add the initial tweakey to the state */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Perform the two rounds of this step */ + #define clyde128_sbox(s0, s1, s2, s3) \ + do { \ + c = (s0 & s1) ^ s2; \ + d = (s3 & s0) ^ s1; \ + s2 = (c & d) ^ s3; \ + s3 = (c & s3) ^ s0; \ + s0 = d; \ + s1 = c; \ + } while (0) + #define clyde128_lbox(x, y) \ + do { \ + c = x ^ rightRotate12(x); \ + d = y ^ rightRotate12(y); \ + c ^= rightRotate3(c); \ + d ^= rightRotate3(d); \ + x = c ^ leftRotate15(x); \ + y = d ^ leftRotate15(y); \ + c = x ^ leftRotate1(x); \ + d = y ^ leftRotate1(y); \ + x ^= leftRotate6(d); \ + y ^= leftRotate7(c); \ + x ^= rightRotate15(c); \ + y ^= rightRotate15(d); \ + } while (0) + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + + /* Update the tweakey on the fly and add it to the state */ + c = t2 ^ t0; + d = t3 ^ t1; + t2 = t0; + t3 = t1; + t0 = c; + t1 = d; + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + } + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t a, b, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); +#endif + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all rounds in pairs */ + for (step = CLYDE128_STEPS - 1; step >= 0; --step) { + /* Add the tweakey to the state and update the tweakey */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + a = t2 ^ t0; + b = t3 ^ t1; + t0 = t2; + t1 = t3; + t2 = a; + t3 = b; + + /* Perform the two rounds of this step */ + #define clyde128_inv_sbox(s0, s1, s2, s3) \ + do { \ + d = (s0 & s1) ^ s2; \ + a = (s1 & d) ^ s3; \ + b = (d & a) ^ s0; \ + s2 = (a & b) ^ s1; \ + s0 = a; \ + s1 = b; \ + s3 = d; \ + } while (0) + #define clyde128_inv_lbox(x, y) \ + do { \ + a = x ^ leftRotate7(x); \ + b = y ^ leftRotate7(y); \ + x ^= leftRotate1(a); \ + y ^= leftRotate1(b); \ + x ^= leftRotate12(a); \ + y ^= leftRotate12(b); \ + a = x ^ leftRotate1(x); \ + b = y ^ leftRotate1(y); \ + x ^= leftRotate6(b); \ + y ^= leftRotate7(a); \ + a ^= leftRotate15(x); \ + b ^= leftRotate15(y); \ + x = rightRotate16(a); \ + y = rightRotate16(b); \ + } while (0) + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + } + + /* Add the tweakey to the state one last time */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void shadow512(shadow512_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t s30, s31, s32, s33; + uint32_t c, d, w, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; + s30 = state->W[12]; + s31 = state->W[13]; + s32 = state->W[14]; + s33 = state->W[15]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); + s30 = le_load_word32(state->B + 48); + s31 = le_load_word32(state->B + 52); + s32 = le_load_word32(state->B + 56); + s33 = le_load_word32(state->B + 60); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the S-box and L-box to bundle 3 */ + clyde128_sbox(s30, s31, s32, s33); + clyde128_lbox(s30, s31); + clyde128_lbox(s32, s33); + s30 ^= rc[step][0] << 3; + s31 ^= rc[step][1] << 3; + s32 ^= rc[step][2] << 3; + s33 ^= rc[step][3] << 3; + clyde128_sbox(s30, s31, s32, s33); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow512_diffusion_layer(row) \ + do { \ + w = s0##row; \ + x = s1##row; \ + y = s2##row; \ + z = s3##row; \ + c = w ^ x; \ + d = y ^ z; \ + s0##row = x ^ d; \ + s1##row = w ^ d; \ + s2##row = c ^ z; \ + s3##row = c ^ y; \ + } while (0) + shadow512_diffusion_layer(0); + shadow512_diffusion_layer(1); + shadow512_diffusion_layer(2); + shadow512_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + s30 ^= rc[step][4] << 3; + s31 ^= rc[step][5] << 3; + s32 ^= rc[step][6] << 3; + s33 ^= rc[step][7] << 3; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; + state->W[12] = s30; + state->W[13] = s31; + state->W[14] = s32; + state->W[15] = s33; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); + le_store_word32(state->B + 48, s30); + le_store_word32(state->B + 52, s31); + le_store_word32(state->B + 56, s32); + le_store_word32(state->B + 60, s33); +#endif +} + +void shadow384(shadow384_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t c, d, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow384_diffusion_layer(row) \ + do { \ + x = s0##row; \ + y = s1##row; \ + z = s2##row; \ + s0##row = x ^ y ^ z; \ + s1##row = x ^ z; \ + s2##row = x ^ y; \ + } while (0) + shadow384_diffusion_layer(0); + shadow384_diffusion_layer(1); + shadow384_diffusion_layer(2); + shadow384_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); +#endif +} diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.h b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.h new file mode 100644 index 0000000..b08ce80 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-spook.h @@ -0,0 +1,146 @@ +/* + * 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_SPOOK_H +#define LW_INTERNAL_SPOOK_H + +#include "internal-util.h" + +/** + * \file internal-spook.h + * \brief Internal implementation details of the Spook AEAD mode. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the block for the Clyde-128 block cipher. + */ +#define CLYDE128_BLOCK_SIZE 16 + +/** + * \brief Size of the key for the Clyde-128 block cipher. + */ +#define CLYDE128_KEY_SIZE 16 + +/** + * \brief Size of the tweak for the Clyde-128 block cipher. + */ +#define CLYDE128_TWEAK_SIZE 16 + +/** + * \brief Size of the state for Shadow-512. + */ +#define SHADOW512_STATE_SIZE 64 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-512 state. + */ +#define SHADOW512_RATE 32 + +/** + * \brief Size of the state for Shadow-384. + */ +#define SHADOW384_STATE_SIZE 48 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-384 state. + */ +#define SHADOW384_RATE 16 + +/** + * \brief Internal state of the Shadow-512 permutation. + */ +typedef union +{ + uint32_t W[SHADOW512_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW512_STATE_SIZE]; /**< Bytes of the state */ + +} shadow512_state_t; + +/** + * \brief Internal state of the Shadow-384 permutation. + */ +typedef union +{ + uint32_t W[SHADOW384_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW384_STATE_SIZE]; /**< Bytes of the state */ + +} shadow384_state_t; + +/** + * \brief Encrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to encrypt with. + * \param tweak Points to the tweak to encrypt with. + * \param output Output buffer for the ciphertext. + * \param input Input buffer for the plaintext. + * + * \sa clyde128_decrypt() + */ +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); + +/** + * \brief Decrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to decrypt with. + * \param tweak Points to the tweak to decrypt with. + * \param output Output buffer for the plaintext. + * \param input Input buffer for the ciphertext. + * + * \sa clyde128_encrypt() + */ +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]); + +/** + * \brief Performs the Shadow-512 permutation on a state. + * + * \param state The Shadow-512 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow384() + */ +void shadow512(shadow512_state_t *state); + +/** + * \brief Performs the Shadow-384 permutation on a state. + * + * \param state The Shadow-384 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow512() + */ +void shadow384(shadow384_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-util.h b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.c b/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.c new file mode 100644 index 0000000..d075b33 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.c @@ -0,0 +1,552 @@ +/* + * 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 "spook.h" +#include "internal-spook.h" +#include "internal-util.h" +#include + +aead_cipher_t const spook_128_512_su_cipher = { + "Spook-128-512-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_su_aead_encrypt, + spook_128_512_su_aead_decrypt +}; + +aead_cipher_t const spook_128_384_su_cipher = { + "Spook-128-384-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_su_aead_encrypt, + spook_128_384_su_aead_decrypt +}; + +aead_cipher_t const spook_128_512_mu_cipher = { + "Spook-128-512-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_mu_aead_encrypt, + spook_128_512_mu_aead_decrypt +}; + +aead_cipher_t const spook_128_384_mu_cipher = { + "Spook-128-384-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_mu_aead_encrypt, + spook_128_384_mu_aead_decrypt +}; + +/** + * \brief Initializes the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_512_init + (shadow512_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW512_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 12, state->W + 4); + shadow512(state); +} + +/** + * \brief Initializes the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_384_init + (shadow384_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW384_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 8, state->W + 4); + shadow384(state); +} + +/** + * \brief Absorbs associated data into the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_512_absorb + (shadow512_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW512_RATE) { + lw_xor_block(state->B, ad, SHADOW512_RATE); + shadow512(state); + ad += SHADOW512_RATE; + adlen -= SHADOW512_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Absorbs associated data into the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_384_absorb + (shadow384_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW384_RATE) { + lw_xor_block(state->B, ad, SHADOW384_RATE); + shadow384(state); + ad += SHADOW384_RATE; + adlen -= SHADOW384_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_512_encrypt + (shadow512_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (mlen >= SHADOW512_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + mlen -= SHADOW512_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_384_encrypt + (shadow384_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (mlen >= SHADOW384_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + mlen -= SHADOW384_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_512_decrypt + (shadow512_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (clen >= SHADOW512_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + clen -= SHADOW512_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_384_decrypt + (shadow384_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (clen >= SHADOW384_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + clen -= SHADOW384_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} diff --git a/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.h b/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.h new file mode 100644 index 0000000..68b6a25 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su384v1/rhys/spook.h @@ -0,0 +1,344 @@ +/* + * 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_SPOOK_H +#define LWCRYPTO_SPOOK_H + +#include "aead-common.h" + +/** + * \file spook.h + * \brief Spook authenticated encryption algorithm. + * + * Spook is a family of authenticated encryption algorithms that are + * built around a tweakable block cipher and a permutation. If the + * tweakable block cipher is implemented as a masked block cipher, + * then Spook provides protection against power analysis side channels. + * + * There are four members in the Spook family: + * + * \li Spook-128-512-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 512-bit permutation. This is the primary + * member of the family. + * \li Spook-128-384-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 384-bit permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 512-bit + * permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 384-bit + * permutation. + * + * In this library, the "mu" (multi-user) variants combine the 128-bit key + * and the 128-bit public tweak into a single 256-bit key value. + * Applications can either view this as a cipher with a 256-bit key, + * or they can split the key value into secret and public halves. + * Even with the use of 256-bit keys, Spook only has 128-bit security. + * + * References: https://www.spook.dev/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for the single-user version of Spook. + */ +#define SPOOK_SU_KEY_SIZE 16 + +/** + * \brief Size of the key for the multi-user version of Spook. + */ +#define SPOOK_MU_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all Spook family members. + */ +#define SPOOK_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all Spook family members. + */ +#define SPOOK_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the Spook-128-512-su cipher. + */ +extern aead_cipher_t const spook_128_512_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-su cipher. + */ +extern aead_cipher_t const spook_128_384_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-512-mu cipher. + */ +extern aead_cipher_t const spook_128_512_mu_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-mu cipher. + */ +extern aead_cipher_t const spook_128_384_mu_cipher; + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_su_aead_decrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_512_su_aead_encrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_su_aead_decrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_384_su_aead_encrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_mu_aead_decrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_512_mu_aead_encrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_mu_aead_decrypt() + */ +int spook_128_384_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_384_mu_aead_encrypt() + */ +int spook_128_384_mu_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.c b/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.h b/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/api.h b/spook/Implementations/crypto_aead/spook128su512v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/encrypt.c b/spook/Implementations/crypto_aead/spook128su512v1/rhys/encrypt.c new file mode 100644 index 0000000..0d3db2e --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "spook.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 spook_128_512_su_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 spook_128_512_su_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.c b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.c new file mode 100644 index 0000000..0e19216 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.c @@ -0,0 +1,557 @@ +/* + * 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 "internal-spook.h" + +/** + * \brief Number of steps in the Clyde-128 block cipher. + * + * This is also the number of steps in the Shadow-512 and Shadow-384 + * permutations. + */ +#define CLYDE128_STEPS 6 + +/** + * \brief Round constants for the steps of Clyde-128. + */ +static uint8_t const rc[CLYDE128_STEPS][8] = { + {1, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 1}, + {1, 1, 0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 0, 0, 1, 0, 1}, + {1, 1, 1, 0, 0, 1, 1, 1} +}; + +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t c, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); + s0 = le_load_word32((const unsigned char *)&(input[0])); + s1 = le_load_word32((const unsigned char *)&(input[1])); + s2 = le_load_word32((const unsigned char *)&(input[2])); + s3 = le_load_word32((const unsigned char *)&(input[3])); +#endif + + /* Add the initial tweakey to the state */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Perform the two rounds of this step */ + #define clyde128_sbox(s0, s1, s2, s3) \ + do { \ + c = (s0 & s1) ^ s2; \ + d = (s3 & s0) ^ s1; \ + s2 = (c & d) ^ s3; \ + s3 = (c & s3) ^ s0; \ + s0 = d; \ + s1 = c; \ + } while (0) + #define clyde128_lbox(x, y) \ + do { \ + c = x ^ rightRotate12(x); \ + d = y ^ rightRotate12(y); \ + c ^= rightRotate3(c); \ + d ^= rightRotate3(d); \ + x = c ^ leftRotate15(x); \ + y = d ^ leftRotate15(y); \ + c = x ^ leftRotate1(x); \ + d = y ^ leftRotate1(y); \ + x ^= leftRotate6(d); \ + y ^= leftRotate7(c); \ + x ^= rightRotate15(c); \ + y ^= rightRotate15(d); \ + } while (0) + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_sbox(s0, s1, s2, s3); + clyde128_lbox(s0, s1); + clyde128_lbox(s2, s3); + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + + /* Update the tweakey on the fly and add it to the state */ + c = t2 ^ t0; + d = t3 ^ t1; + t2 = t0; + t3 = t1; + t0 = c; + t1 = d; + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + } + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]) +{ + uint32_t k0, k1, k2, k3; + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t a, b, d; + int step; + + /* Unpack the key, tweak, and state */ + k0 = le_load_word32(key); + k1 = le_load_word32(key + 4); + k2 = le_load_word32(key + 8); + k3 = le_load_word32(key + 12); +#if defined(LW_UTIL_LITTLE_ENDIAN) + t0 = tweak[0]; + t1 = tweak[1]; + t2 = tweak[2]; + t3 = tweak[3]; +#else + t0 = le_load_word32((const unsigned char *)&(tweak[0])); + t1 = le_load_word32((const unsigned char *)&(tweak[1])); + t2 = le_load_word32((const unsigned char *)&(tweak[2])); + t3 = le_load_word32((const unsigned char *)&(tweak[3])); +#endif + s0 = le_load_word32(input); + s1 = le_load_word32(input + 4); + s2 = le_load_word32(input + 8); + s3 = le_load_word32(input + 12); + + /* Perform all rounds in pairs */ + for (step = CLYDE128_STEPS - 1; step >= 0; --step) { + /* Add the tweakey to the state and update the tweakey */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + a = t2 ^ t0; + b = t3 ^ t1; + t0 = t2; + t1 = t3; + t2 = a; + t3 = b; + + /* Perform the two rounds of this step */ + #define clyde128_inv_sbox(s0, s1, s2, s3) \ + do { \ + d = (s0 & s1) ^ s2; \ + a = (s1 & d) ^ s3; \ + b = (d & a) ^ s0; \ + s2 = (a & b) ^ s1; \ + s0 = a; \ + s1 = b; \ + s3 = d; \ + } while (0) + #define clyde128_inv_lbox(x, y) \ + do { \ + a = x ^ leftRotate7(x); \ + b = y ^ leftRotate7(y); \ + x ^= leftRotate1(a); \ + y ^= leftRotate1(b); \ + x ^= leftRotate12(a); \ + y ^= leftRotate12(b); \ + a = x ^ leftRotate1(x); \ + b = y ^ leftRotate1(y); \ + x ^= leftRotate6(b); \ + y ^= leftRotate7(a); \ + a ^= leftRotate15(x); \ + b ^= leftRotate15(y); \ + x = rightRotate16(a); \ + y = rightRotate16(b); \ + } while (0) + s0 ^= rc[step][4]; + s1 ^= rc[step][5]; + s2 ^= rc[step][6]; + s3 ^= rc[step][7]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + s0 ^= rc[step][0]; + s1 ^= rc[step][1]; + s2 ^= rc[step][2]; + s3 ^= rc[step][3]; + clyde128_inv_lbox(s0, s1); + clyde128_inv_lbox(s2, s3); + clyde128_inv_sbox(s0, s1, s2, s3); + } + + /* Add the tweakey to the state one last time */ + s0 ^= k0 ^ t0; + s1 ^= k1 ^ t1; + s2 ^= k2 ^ t2; + s3 ^= k3 ^ t3; + + /* Pack the state into the output buffer */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +#else + le_store_word32((unsigned char *)&(output[0]), s0); + le_store_word32((unsigned char *)&(output[1]), s1); + le_store_word32((unsigned char *)&(output[2]), s2); + le_store_word32((unsigned char *)&(output[3]), s3); +#endif +} + +void shadow512(shadow512_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t s30, s31, s32, s33; + uint32_t c, d, w, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; + s30 = state->W[12]; + s31 = state->W[13]; + s32 = state->W[14]; + s33 = state->W[15]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); + s30 = le_load_word32(state->B + 48); + s31 = le_load_word32(state->B + 52); + s32 = le_load_word32(state->B + 56); + s33 = le_load_word32(state->B + 60); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the S-box and L-box to bundle 3 */ + clyde128_sbox(s30, s31, s32, s33); + clyde128_lbox(s30, s31); + clyde128_lbox(s32, s33); + s30 ^= rc[step][0] << 3; + s31 ^= rc[step][1] << 3; + s32 ^= rc[step][2] << 3; + s33 ^= rc[step][3] << 3; + clyde128_sbox(s30, s31, s32, s33); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow512_diffusion_layer(row) \ + do { \ + w = s0##row; \ + x = s1##row; \ + y = s2##row; \ + z = s3##row; \ + c = w ^ x; \ + d = y ^ z; \ + s0##row = x ^ d; \ + s1##row = w ^ d; \ + s2##row = c ^ z; \ + s3##row = c ^ y; \ + } while (0) + shadow512_diffusion_layer(0); + shadow512_diffusion_layer(1); + shadow512_diffusion_layer(2); + shadow512_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + s30 ^= rc[step][4] << 3; + s31 ^= rc[step][5] << 3; + s32 ^= rc[step][6] << 3; + s33 ^= rc[step][7] << 3; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; + state->W[12] = s30; + state->W[13] = s31; + state->W[14] = s32; + state->W[15] = s33; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); + le_store_word32(state->B + 48, s30); + le_store_word32(state->B + 52, s31); + le_store_word32(state->B + 56, s32); + le_store_word32(state->B + 60, s33); +#endif +} + +void shadow384(shadow384_state_t *state) +{ + uint32_t s00, s01, s02, s03; + uint32_t s10, s11, s12, s13; + uint32_t s20, s21, s22, s23; + uint32_t c, d, x, y, z; + int step; + + /* Unpack the state into local variables */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + s00 = state->W[0]; + s01 = state->W[1]; + s02 = state->W[2]; + s03 = state->W[3]; + s10 = state->W[4]; + s11 = state->W[5]; + s12 = state->W[6]; + s13 = state->W[7]; + s20 = state->W[8]; + s21 = state->W[9]; + s22 = state->W[10]; + s23 = state->W[11]; +#else + s00 = le_load_word32(state->B); + s01 = le_load_word32(state->B + 4); + s02 = le_load_word32(state->B + 8); + s03 = le_load_word32(state->B + 12); + s10 = le_load_word32(state->B + 16); + s11 = le_load_word32(state->B + 20); + s12 = le_load_word32(state->B + 24); + s13 = le_load_word32(state->B + 28); + s20 = le_load_word32(state->B + 32); + s21 = le_load_word32(state->B + 36); + s22 = le_load_word32(state->B + 40); + s23 = le_load_word32(state->B + 44); +#endif + + /* Perform all rounds in pairs */ + for (step = 0; step < CLYDE128_STEPS; ++step) { + /* Apply the S-box and L-box to bundle 0 */ + clyde128_sbox(s00, s01, s02, s03); + clyde128_lbox(s00, s01); + clyde128_lbox(s02, s03); + s00 ^= rc[step][0]; + s01 ^= rc[step][1]; + s02 ^= rc[step][2]; + s03 ^= rc[step][3]; + clyde128_sbox(s00, s01, s02, s03); + + /* Apply the S-box and L-box to bundle 1 */ + clyde128_sbox(s10, s11, s12, s13); + clyde128_lbox(s10, s11); + clyde128_lbox(s12, s13); + s10 ^= rc[step][0] << 1; + s11 ^= rc[step][1] << 1; + s12 ^= rc[step][2] << 1; + s13 ^= rc[step][3] << 1; + clyde128_sbox(s10, s11, s12, s13); + + /* Apply the S-box and L-box to bundle 2 */ + clyde128_sbox(s20, s21, s22, s23); + clyde128_lbox(s20, s21); + clyde128_lbox(s22, s23); + s20 ^= rc[step][0] << 2; + s21 ^= rc[step][1] << 2; + s22 ^= rc[step][2] << 2; + s23 ^= rc[step][3] << 2; + clyde128_sbox(s20, s21, s22, s23); + + /* Apply the diffusion layer to the rows of the state */ + #define shadow384_diffusion_layer(row) \ + do { \ + x = s0##row; \ + y = s1##row; \ + z = s2##row; \ + s0##row = x ^ y ^ z; \ + s1##row = x ^ z; \ + s2##row = x ^ y; \ + } while (0) + shadow384_diffusion_layer(0); + shadow384_diffusion_layer(1); + shadow384_diffusion_layer(2); + shadow384_diffusion_layer(3); + + /* Add round constants to all bundles again */ + s00 ^= rc[step][4]; + s01 ^= rc[step][5]; + s02 ^= rc[step][6]; + s03 ^= rc[step][7]; + s10 ^= rc[step][4] << 1; + s11 ^= rc[step][5] << 1; + s12 ^= rc[step][6] << 1; + s13 ^= rc[step][7] << 1; + s20 ^= rc[step][4] << 2; + s21 ^= rc[step][5] << 2; + s22 ^= rc[step][6] << 2; + s23 ^= rc[step][7] << 2; + } + + /* Pack the local variables back into the state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->W[0] = s00; + state->W[1] = s01; + state->W[2] = s02; + state->W[3] = s03; + state->W[4] = s10; + state->W[5] = s11; + state->W[6] = s12; + state->W[7] = s13; + state->W[8] = s20; + state->W[9] = s21; + state->W[10] = s22; + state->W[11] = s23; +#else + le_store_word32(state->B, s00); + le_store_word32(state->B + 4, s01); + le_store_word32(state->B + 8, s02); + le_store_word32(state->B + 12, s03); + le_store_word32(state->B + 16, s10); + le_store_word32(state->B + 20, s11); + le_store_word32(state->B + 24, s12); + le_store_word32(state->B + 28, s13); + le_store_word32(state->B + 32, s20); + le_store_word32(state->B + 36, s21); + le_store_word32(state->B + 40, s22); + le_store_word32(state->B + 44, s23); +#endif +} diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.h b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.h new file mode 100644 index 0000000..b08ce80 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-spook.h @@ -0,0 +1,146 @@ +/* + * 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_SPOOK_H +#define LW_INTERNAL_SPOOK_H + +#include "internal-util.h" + +/** + * \file internal-spook.h + * \brief Internal implementation details of the Spook AEAD mode. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the block for the Clyde-128 block cipher. + */ +#define CLYDE128_BLOCK_SIZE 16 + +/** + * \brief Size of the key for the Clyde-128 block cipher. + */ +#define CLYDE128_KEY_SIZE 16 + +/** + * \brief Size of the tweak for the Clyde-128 block cipher. + */ +#define CLYDE128_TWEAK_SIZE 16 + +/** + * \brief Size of the state for Shadow-512. + */ +#define SHADOW512_STATE_SIZE 64 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-512 state. + */ +#define SHADOW512_RATE 32 + +/** + * \brief Size of the state for Shadow-384. + */ +#define SHADOW384_STATE_SIZE 48 + +/** + * \brief Rate to absorb data into or squeeze data out of a Shadow-384 state. + */ +#define SHADOW384_RATE 16 + +/** + * \brief Internal state of the Shadow-512 permutation. + */ +typedef union +{ + uint32_t W[SHADOW512_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW512_STATE_SIZE]; /**< Bytes of the state */ + +} shadow512_state_t; + +/** + * \brief Internal state of the Shadow-384 permutation. + */ +typedef union +{ + uint32_t W[SHADOW384_STATE_SIZE / 4]; /**< Words of the state */ + uint8_t B[SHADOW384_STATE_SIZE]; /**< Bytes of the state */ + +} shadow384_state_t; + +/** + * \brief Encrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to encrypt with. + * \param tweak Points to the tweak to encrypt with. + * \param output Output buffer for the ciphertext. + * \param input Input buffer for the plaintext. + * + * \sa clyde128_decrypt() + */ +void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); + +/** + * \brief Decrypts a block with the Clyde-128 block cipher. + * + * \param key Points to the key to decrypt with. + * \param tweak Points to the tweak to decrypt with. + * \param output Output buffer for the plaintext. + * \param input Input buffer for the ciphertext. + * + * \sa clyde128_encrypt() + */ +void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], + const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4], + uint32_t output[CLYDE128_BLOCK_SIZE / 4], + const unsigned char input[CLYDE128_BLOCK_SIZE]); + +/** + * \brief Performs the Shadow-512 permutation on a state. + * + * \param state The Shadow-512 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow384() + */ +void shadow512(shadow512_state_t *state); + +/** + * \brief Performs the Shadow-384 permutation on a state. + * + * \param state The Shadow-384 state which will be in little-endian + * byte order on input and output. + * + * \sa shadow512() + */ +void shadow384(shadow384_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-util.h b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.c b/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.c new file mode 100644 index 0000000..d075b33 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.c @@ -0,0 +1,552 @@ +/* + * 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 "spook.h" +#include "internal-spook.h" +#include "internal-util.h" +#include + +aead_cipher_t const spook_128_512_su_cipher = { + "Spook-128-512-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_su_aead_encrypt, + spook_128_512_su_aead_decrypt +}; + +aead_cipher_t const spook_128_384_su_cipher = { + "Spook-128-384-su", + SPOOK_SU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_su_aead_encrypt, + spook_128_384_su_aead_decrypt +}; + +aead_cipher_t const spook_128_512_mu_cipher = { + "Spook-128-512-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_512_mu_aead_encrypt, + spook_128_512_mu_aead_decrypt +}; + +aead_cipher_t const spook_128_384_mu_cipher = { + "Spook-128-384-mu", + SPOOK_MU_KEY_SIZE, + SPOOK_NONCE_SIZE, + SPOOK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + spook_128_384_mu_aead_encrypt, + spook_128_384_mu_aead_decrypt +}; + +/** + * \brief Initializes the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_512_init + (shadow512_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW512_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 12, state->W + 4); + shadow512(state); +} + +/** + * \brief Initializes the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param k Points to the key. + * \param klen Length of the key in bytes, either 16 or 32. + * \param npub Public nonce for the state. + */ +static void spook_128_384_init + (shadow384_state_t *state, + const unsigned char *k, unsigned klen, + const unsigned char *npub) +{ + memset(state->B, 0, SHADOW384_STATE_SIZE); + if (klen == SPOOK_MU_KEY_SIZE) { + /* The public tweak is 126 bits in size followed by a 1 bit */ + memcpy(state->B, k + CLYDE128_BLOCK_SIZE, CLYDE128_BLOCK_SIZE); + state->B[CLYDE128_BLOCK_SIZE - 1] &= 0x7F; + state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; + } + memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); + clyde128_encrypt(k, state->W, state->W + 8, state->W + 4); + shadow384(state); +} + +/** + * \brief Absorbs associated data into the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_512_absorb + (shadow512_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW512_RATE) { + lw_xor_block(state->B, ad, SHADOW512_RATE); + shadow512(state); + ad += SHADOW512_RATE; + adlen -= SHADOW512_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Absorbs associated data into the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes, must be non-zero. + */ +static void spook_128_384_absorb + (shadow384_state_t *state, + const unsigned char *ad, unsigned long long adlen) +{ + while (adlen >= SHADOW384_RATE) { + lw_xor_block(state->B, ad, SHADOW384_RATE); + shadow384(state); + ad += SHADOW384_RATE; + adlen -= SHADOW384_RATE; + } + if (adlen > 0) { + unsigned temp = (unsigned)adlen; + lw_xor_block(state->B, ad, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_512_encrypt + (shadow512_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (mlen >= SHADOW512_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + mlen -= SHADOW512_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Encrypts the plaintext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Number of bytes of plaintext to be encrypted. + */ +static void spook_128_384_encrypt + (shadow384_state_t *state, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (mlen >= SHADOW384_RATE) { + lw_xor_block_2_dest(c, state->B, m, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + mlen -= SHADOW384_RATE; + } + if (mlen > 0) { + unsigned temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state->B, m, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-512 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_512_decrypt + (shadow512_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW512_RATE] ^= 0x01; + while (clen >= SHADOW512_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW512_RATE); + shadow512(state); + c += SHADOW512_RATE; + m += SHADOW512_RATE; + clen -= SHADOW512_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW512_RATE] ^= 0x02; + shadow512(state); + } +} + +/** + * \brief Decrypts the ciphertext with the Shadow-384 sponge state. + * + * \param state The sponge state. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param clen Number of bytes of ciphertext to be decrypted. + */ +static void spook_128_384_decrypt + (shadow384_state_t *state, unsigned char *m, + const unsigned char *c, unsigned long long clen) +{ + state->B[SHADOW384_RATE] ^= 0x01; + while (clen >= SHADOW384_RATE) { + lw_xor_block_swap(m, state->B, c, SHADOW384_RATE); + shadow384(state); + c += SHADOW384_RATE; + m += SHADOW384_RATE; + clen -= SHADOW384_RATE; + } + if (clen > 0) { + unsigned temp = (unsigned)clen; + lw_xor_block_swap(m, state->B, c, temp); + state->B[temp] ^= 0x01; + state->B[SHADOW384_RATE] ^= 0x02; + shadow384(state); + } +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_su_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_su_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_SU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_512_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_512_mu_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) +{ + shadow512_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-512 sponge state */ + spook_128_512_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_512_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_512_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + if (mlen > 0) + spook_128_384_encrypt(&state, c, m, mlen); + + /* Compute the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_encrypt(k, state.W + 4, state.W, state.W); + memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); + return 0; +} + +int spook_128_384_mu_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) +{ + shadow384_state_t state; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SPOOK_TAG_SIZE) + return -1; + *mlen = clen - SPOOK_TAG_SIZE; + + /* Initialize the Shadow-384 sponge state */ + spook_128_384_init(&state, k, SPOOK_MU_KEY_SIZE, npub); + + /* Process the associated data */ + if (adlen > 0) + spook_128_384_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SPOOK_TAG_SIZE; + if (clen > 0) + spook_128_384_decrypt(&state, m, c, clen); + + /* Check the authentication tag */ + state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; + clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); + return aead_check_tag + (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); +} diff --git a/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.h b/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.h new file mode 100644 index 0000000..68b6a25 --- /dev/null +++ b/spook/Implementations/crypto_aead/spook128su512v1/rhys/spook.h @@ -0,0 +1,344 @@ +/* + * 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_SPOOK_H +#define LWCRYPTO_SPOOK_H + +#include "aead-common.h" + +/** + * \file spook.h + * \brief Spook authenticated encryption algorithm. + * + * Spook is a family of authenticated encryption algorithms that are + * built around a tweakable block cipher and a permutation. If the + * tweakable block cipher is implemented as a masked block cipher, + * then Spook provides protection against power analysis side channels. + * + * There are four members in the Spook family: + * + * \li Spook-128-512-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 512-bit permutation. This is the primary + * member of the family. + * \li Spook-128-384-su with a 128-bit key, a 128-bit nonce, and a 128-bit tag. + * Internally the algorithm uses a 384-bit permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 512-bit + * permutation. + * \li Spook-128-512-mu with a 128-bit key, a 128-bit public tweak, a 128-bit + * nonce, and a 128-bit tag. Internally the algorithm uses a 384-bit + * permutation. + * + * In this library, the "mu" (multi-user) variants combine the 128-bit key + * and the 128-bit public tweak into a single 256-bit key value. + * Applications can either view this as a cipher with a 256-bit key, + * or they can split the key value into secret and public halves. + * Even with the use of 256-bit keys, Spook only has 128-bit security. + * + * References: https://www.spook.dev/ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for the single-user version of Spook. + */ +#define SPOOK_SU_KEY_SIZE 16 + +/** + * \brief Size of the key for the multi-user version of Spook. + */ +#define SPOOK_MU_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all Spook family members. + */ +#define SPOOK_TAG_SIZE 16 + +/** + * \brief Size of the nonce for all Spook family members. + */ +#define SPOOK_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the Spook-128-512-su cipher. + */ +extern aead_cipher_t const spook_128_512_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-su cipher. + */ +extern aead_cipher_t const spook_128_384_su_cipher; + +/** + * \brief Meta-information block for the Spook-128-512-mu cipher. + */ +extern aead_cipher_t const spook_128_512_mu_cipher; + +/** + * \brief Meta-information block for the Spook-128-384-mu cipher. + */ +extern aead_cipher_t const spook_128_384_mu_cipher; + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_su_aead_decrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_512_su_aead_encrypt() + */ +int spook_128_512_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-su. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_su_aead_decrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-su. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa spook_128_384_su_aead_encrypt() + */ +int spook_128_384_su_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-512-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_512_mu_aead_decrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-512-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_512_mu_aead_encrypt() + */ +int spook_128_512_mu_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); + +/** + * \brief Encrypts and authenticates a packet with Spook-128-384-mu. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa spook_128_384_mu_aead_decrypt() + */ +int spook_128_384_mu_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); + +/** + * \brief Decrypts and authenticates a packet with Spook-128-384-mu. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa spook_128_384_mu_aead_encrypt() + */ +int spook_128_384_mu_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.c b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.h b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/api.h b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/encrypt.c b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/encrypt.c new file mode 100644 index 0000000..2f166ad --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "subterranean.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 subterranean_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 subterranean_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.c b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.c new file mode 100644 index 0000000..1cb64e2 --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.c @@ -0,0 +1,441 @@ +/* + * 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 "internal-subterranean.h" +#include + +void subterranean_round(subterranean_state_t *state) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8; + uint32_t t0, t1; + + /* Load the state up into local variables */ + x0 = state->x[0]; + x1 = state->x[1]; + x2 = state->x[2]; + x3 = state->x[3]; + x4 = state->x[4]; + x5 = state->x[5]; + x6 = state->x[6]; + x7 = state->x[7]; + x8 = state->x[8]; + + /* Step chi: s[i] = s[i] ^ (~(s[i+1) & s[i+2]) */ + #define CHI(a, b) \ + do { \ + t0 = ((a) >> 1) | ((b) << 31); \ + t1 = ((a) >> 2) | ((b) << 30); \ + (a) ^= (~t0) & t1; \ + } while (0) + x8 ^= (x0 << 1); + CHI(x0, x1); CHI(x1, x2); + CHI(x2, x3); CHI(x3, x4); + CHI(x4, x5); CHI(x5, x6); + CHI(x6, x7); CHI(x7, x8); + x8 ^= (~(x8 >> 1)) & (x8 >> 2); + + /* Step itoa: invert s[0] */ + x0 ^= 1U; + + /* Step theta: s[i] = s[i] ^ s[i + 3] ^ s[i + 8] */ + #define THETA(a, b) \ + do { \ + t0 = ((a) >> 3) | ((b) << 29); \ + t1 = ((a) >> 8) | ((b) << 24); \ + (a) ^= t0 ^ t1; \ + } while (0) + x8 = (x8 & 1U) ^ (x0 << 1); + THETA(x0, x1); THETA(x1, x2); + THETA(x2, x3); THETA(x3, x4); + THETA(x4, x5); THETA(x5, x6); + THETA(x6, x7); THETA(x7, x8); + x8 ^= (x8 >> 3) ^ (x8 >> 8); + + /* Step pi: permute the bits with the rule s[i] = s[(i * 12) % 257]. + * BCP = bit copy, BUP = move bit up, BDN = move bit down */ + #define BCP(x, bit) ((x) & (((uint32_t)1) << (bit))) + #define BUP(x, from, to) \ + (((x) << ((to) - (from))) & (((uint32_t)1) << (to))) + #define BDN(x, from, to) \ + (((x) >> ((from) - (to))) & (((uint32_t)1) << (to))) + state->x[0] = BCP(x0, 0) ^ BDN(x0, 12, 1) ^ BDN(x0, 24, 2) ^ + BDN(x1, 4, 3) ^ BDN(x1, 16, 4) ^ BDN(x1, 28, 5) ^ + BDN(x2, 8, 6) ^ BDN(x2, 20, 7) ^ BUP(x3, 0, 8) ^ + BDN(x3, 12, 9) ^ BDN(x3, 24, 10) ^ BUP(x4, 4, 11) ^ + BDN(x4, 16, 12) ^ BDN(x4, 28, 13) ^ BUP(x5, 8, 14) ^ + BDN(x5, 20, 15) ^ BUP(x6, 0, 16) ^ BUP(x6, 12, 17) ^ + BDN(x6, 24, 18) ^ BUP(x7, 4, 19) ^ BUP(x7, 16, 20) ^ + BDN(x7, 28, 21) ^ BUP(x0, 7, 22) ^ BUP(x0, 19, 23) ^ + BDN(x0, 31, 24) ^ BUP(x1, 11, 25) ^ BUP(x1, 23, 26) ^ + BUP(x2, 3, 27) ^ BUP(x2, 15, 28) ^ BUP(x2, 27, 29) ^ + BUP(x3, 7, 30) ^ BUP(x3, 19, 31); + state->x[1] = BDN(x3, 31, 0) ^ BDN(x4, 11, 1) ^ BDN(x4, 23, 2) ^ + BCP(x5, 3) ^ BDN(x5, 15, 4) ^ BDN(x5, 27, 5) ^ + BDN(x6, 7, 6) ^ BDN(x6, 19, 7) ^ BDN(x6, 31, 8) ^ + BDN(x7, 11, 9) ^ BDN(x7, 23, 10) ^ BUP(x0, 2, 11) ^ + BDN(x0, 14, 12) ^ BDN(x0, 26, 13) ^ BUP(x1, 6, 14) ^ + BDN(x1, 18, 15) ^ BDN(x1, 30, 16) ^ BUP(x2, 10, 17) ^ + BDN(x2, 22, 18) ^ BUP(x3, 2, 19) ^ BUP(x3, 14, 20) ^ + BDN(x3, 26, 21) ^ BUP(x4, 6, 22) ^ BUP(x4, 18, 23) ^ + BDN(x4, 30, 24) ^ BUP(x5, 10, 25) ^ BUP(x5, 22, 26) ^ + BUP(x6, 2, 27) ^ BUP(x6, 14, 28) ^ BUP(x6, 26, 29) ^ + BUP(x7, 6, 30) ^ BUP(x7, 18, 31); + state->x[2] = BDN(x7, 30, 0) ^ BDN(x0, 9, 1) ^ BDN(x0, 21, 2) ^ + BUP(x1, 1, 3) ^ BDN(x1, 13, 4) ^ BDN(x1, 25, 5) ^ + BUP(x2, 5, 6) ^ BDN(x2, 17, 7) ^ BDN(x2, 29, 8) ^ + BCP(x3, 9) ^ BDN(x3, 21, 10) ^ BUP(x4, 1, 11) ^ + BDN(x4, 13, 12) ^ BDN(x4, 25, 13) ^ BUP(x5, 5, 14) ^ + BDN(x5, 17, 15) ^ BDN(x5, 29, 16) ^ BUP(x6, 9, 17) ^ + BDN(x6, 21, 18) ^ BUP(x7, 1, 19) ^ BUP(x7, 13, 20) ^ + BDN(x7, 25, 21) ^ BUP(x0, 4, 22) ^ BUP(x0, 16, 23) ^ + BDN(x0, 28, 24) ^ BUP(x1, 8, 25) ^ BUP(x1, 20, 26) ^ + BUP(x2, 0, 27) ^ BUP(x2, 12, 28) ^ BUP(x2, 24, 29) ^ + BUP(x3, 4, 30) ^ BUP(x3, 16, 31); + state->x[3] = BDN(x3, 28, 0) ^ BDN(x4, 8, 1) ^ BDN(x4, 20, 2) ^ + BUP(x5, 0, 3) ^ BDN(x5, 12, 4) ^ BDN(x5, 24, 5) ^ + BUP(x6, 4, 6) ^ BDN(x6, 16, 7) ^ BDN(x6, 28, 8) ^ + BUP(x7, 8, 9) ^ BDN(x7, 20, 10) ^ BUP(x8, 0, 11) ^ + BUP(x0, 11, 12) ^ BDN(x0, 23, 13) ^ BUP(x1, 3, 14) ^ + BCP(x1, 15) ^ BDN(x1, 27, 16) ^ BUP(x2, 7, 17) ^ + BDN(x2, 19, 18) ^ BDN(x2, 31, 19) ^ BUP(x3, 11, 20) ^ + BDN(x3, 23, 21) ^ BUP(x4, 3, 22) ^ BUP(x4, 15, 23) ^ + BDN(x4, 27, 24) ^ BUP(x5, 7, 25) ^ BUP(x5, 19, 26) ^ + BDN(x5, 31, 27) ^ BUP(x6, 11, 28) ^ BUP(x6, 23, 29) ^ + BUP(x7, 3, 30) ^ BUP(x7, 15, 31); + state->x[4] = BDN(x7, 27, 0) ^ BDN(x0, 6, 1) ^ BDN(x0, 18, 2) ^ + BDN(x0, 30, 3) ^ BDN(x1, 10, 4) ^ BDN(x1, 22, 5) ^ + BUP(x2, 2, 6) ^ BDN(x2, 14, 7) ^ BDN(x2, 26, 8) ^ + BUP(x3, 6, 9) ^ BDN(x3, 18, 10) ^ BDN(x3, 30, 11) ^ + BUP(x4, 10, 12) ^ BDN(x4, 22, 13) ^ BUP(x5, 2, 14) ^ + BUP(x5, 14, 15) ^ BDN(x5, 26, 16) ^ BUP(x6, 6, 17) ^ + BCP(x6, 18) ^ BDN(x6, 30, 19) ^ BUP(x7, 10, 20) ^ + BDN(x7, 22, 21) ^ BUP(x0, 1, 22) ^ BUP(x0, 13, 23) ^ + BDN(x0, 25, 24) ^ BUP(x1, 5, 25) ^ BUP(x1, 17, 26) ^ + BDN(x1, 29, 27) ^ BUP(x2, 9, 28) ^ BUP(x2, 21, 29) ^ + BUP(x3, 1, 30) ^ BUP(x3, 13, 31); + state->x[5] = BDN(x3, 25, 0) ^ BDN(x4, 5, 1) ^ BDN(x4, 17, 2) ^ + BDN(x4, 29, 3) ^ BDN(x5, 9, 4) ^ BDN(x5, 21, 5) ^ + BUP(x6, 1, 6) ^ BDN(x6, 13, 7) ^ BDN(x6, 25, 8) ^ + BUP(x7, 5, 9) ^ BDN(x7, 17, 10) ^ BDN(x7, 29, 11) ^ + BUP(x0, 8, 12) ^ BDN(x0, 20, 13) ^ BUP(x1, 0, 14) ^ + BUP(x1, 12, 15) ^ BDN(x1, 24, 16) ^ BUP(x2, 4, 17) ^ + BUP(x2, 16, 18) ^ BDN(x2, 28, 19) ^ BUP(x3, 8, 20) ^ + BUP(x3, 20, 21) ^ BUP(x4, 0, 22) ^ BUP(x4, 12, 23) ^ + BCP(x4, 24) ^ BUP(x5, 4, 25) ^ BUP(x5, 16, 26) ^ + BDN(x5, 28, 27) ^ BUP(x6, 8, 28) ^ BUP(x6, 20, 29) ^ + BUP(x7, 0, 30) ^ BUP(x7, 12, 31); + state->x[6] = BDN(x7, 24, 0) ^ BDN(x0, 3, 1) ^ BDN(x0, 15, 2) ^ + BDN(x0, 27, 3) ^ BDN(x1, 7, 4) ^ BDN(x1, 19, 5) ^ + BDN(x1, 31, 6) ^ BDN(x2, 11, 7) ^ BDN(x2, 23, 8) ^ + BUP(x3, 3, 9) ^ BDN(x3, 15, 10) ^ BDN(x3, 27, 11) ^ + BUP(x4, 7, 12) ^ BDN(x4, 19, 13) ^ BDN(x4, 31, 14) ^ + BUP(x5, 11, 15) ^ BDN(x5, 23, 16) ^ BUP(x6, 3, 17) ^ + BUP(x6, 15, 18) ^ BDN(x6, 27, 19) ^ BUP(x7, 7, 20) ^ + BUP(x7, 19, 21) ^ BDN(x7, 31, 22) ^ BUP(x0, 10, 23) ^ + BUP(x0, 22, 24) ^ BUP(x1, 2, 25) ^ BUP(x1, 14, 26) ^ + BUP(x1, 26, 27) ^ BUP(x2, 6, 28) ^ BUP(x2, 18, 29) ^ + BCP(x2, 30) ^ BUP(x3, 10, 31); + state->x[7] = BDN(x3, 22, 0) ^ BDN(x4, 2, 1) ^ BDN(x4, 14, 2) ^ + BDN(x4, 26, 3) ^ BDN(x5, 6, 4) ^ BDN(x5, 18, 5) ^ + BDN(x5, 30, 6) ^ BDN(x6, 10, 7) ^ BDN(x6, 22, 8) ^ + BUP(x7, 2, 9) ^ BDN(x7, 14, 10) ^ BDN(x7, 26, 11) ^ + BUP(x0, 5, 12) ^ BDN(x0, 17, 13) ^ BDN(x0, 29, 14) ^ + BUP(x1, 9, 15) ^ BDN(x1, 21, 16) ^ BUP(x2, 1, 17) ^ + BUP(x2, 13, 18) ^ BDN(x2, 25, 19) ^ BUP(x3, 5, 20) ^ + BUP(x3, 17, 21) ^ BDN(x3, 29, 22) ^ BUP(x4, 9, 23) ^ + BUP(x4, 21, 24) ^ BUP(x5, 1, 25) ^ BUP(x5, 13, 26) ^ + BUP(x5, 25, 27) ^ BUP(x6, 5, 28) ^ BUP(x6, 17, 29) ^ + BUP(x6, 29, 30) ^ BUP(x7, 9, 31); + state->x[8] = BDN(x7, 21, 0); +} + +void subterranean_blank(subterranean_state_t *state) +{ + unsigned round; + for (round = 0; round < 8; ++round) { + subterranean_round(state); + state->x[0] ^= 0x02; /* padding for an empty block is in state bit 1 */ + } +} + +void subterranean_duplex_0(subterranean_state_t *state) +{ + subterranean_round(state); + state->x[0] ^= 0x02; /* padding for an empty block is in state bit 1 */ +} + +void subterranean_duplex_1(subterranean_state_t *state, unsigned char data) +{ + uint32_t x = data; + + /* Perform a single Subterranean round before absorbing the bits */ + subterranean_round(state); + + /* Rearrange the bits and absorb them into the state */ + state->x[0] ^= (x << 1) & 0x00000002U; + state->x[1] ^= x & 0x00000008U; + state->x[2] ^= 0x00000001U; /* 9th padding bit is always 1 */ + state->x[4] ^= ((x << 6) & 0x00000100U) ^ ((x << 1) & 0x00000040U); + state->x[5] ^= (x << 15) & 0x00010000U; + state->x[6] ^= (x >> 1) & 0x00000020U; + state->x[7] ^= ((x << 21) & 0x02000000U) ^ ((x << 3) & 0x00000400U); +} + +void subterranean_duplex_word(subterranean_state_t *state, uint32_t x) +{ + uint32_t y; + + /* Perform a single Subterranean round before absorbing the bits */ + subterranean_round(state); + + /* To absorb the word into the state, we first rearrange the source + * bits to be in the right target bit positions. Then we mask and + * XOR them into the relevant words of the state. + * + * Some of the source bits end up in the same target bit but a different + * word so we have to permute the input word twice to get all the source + * bits into the locations we want for masking and XOR'ing. + * + * Permutations generated with "http://programming.sirrida.de/calcperm.php". + */ + + /* P1 = [1 16 8 3 25 * * 10 0 21 * 24 2 31 15 6 * 11 9 19 * * 29 * 4 * 30 12 * 22 17 5] */ + y = (x & 0x00080008U) + | ((x & 0x00004001U) << 1) + | ((x & 0x00000080U) << 3) + | ((x & 0x04000000U) << 4) + | leftRotate6(x & 0x80000004U) + | ((x & 0x00400000U) << 7) + | leftRotate12(x & 0x01000200U) + | ((x & 0x00000800U) << 13) + | ((x & 0x00000002U) << 15) + | ((x & 0x08000000U) >> 15) + | ((x & 0x00002000U) << 18) + | ((x & 0x40000000U) >> 13) + | ((x & 0x00000010U) << 21) + | ((x & 0x00001000U) >> 10) + | ((x & 0x00048000U) >> 9) + | ((x & 0x00000100U) >> 8) + | ((x & 0x20000000U) >> 7) + | ((x & 0x00020000U) >> 6); + + /* P2 = [* * * * * 6 5 * * * 31 * * * * * 17 * * * 0 9 * 15 * 30 * * 1 * * *] */ + x = ((x & 0x00010020U) << 1) + | leftRotate5(x & 0x12000000U) + | ((x & 0x00100000U) >> 20) + | ((x & 0x00200000U) >> 12) + | ((x & 0x00000400U) << 21) + | ((x & 0x00800000U) >> 8) + | ((x & 0x00000040U) >> 1); + + /* Integrate the rearranged bits into the state */ + state->x[0] ^= (y & 0x40428816U); + state->x[1] ^= (y & 0x00000008U); + state->x[2] ^= (y & 0x80000041U); + state->x[3] ^= (x & 0x00008000U); + state->x[4] ^= (y & 0x00001300U) ^ (x & 0x00000041U); + state->x[5] ^= (y & 0x21010020U) ^ (x & 0x40000200U); + state->x[6] ^= (y & 0x00280000U) ^ (x & 0x80000020U); + state->x[7] ^= (y & 0x02000400U) ^ (x & 0x00020002U); +} + +void subterranean_duplex_n + (subterranean_state_t *state, const unsigned char *data, unsigned len) +{ + switch (len) { + case 0: + subterranean_duplex_0(state); + break; + case 1: + subterranean_duplex_1(state, data[0]); + break; + case 2: + /* Load 16 bits and add the padding bit to the 17th bit */ + subterranean_duplex_word + (state, ((uint32_t)(data[0]) | + (((uint32_t)(data[1])) << 8) | + 0x10000U)); + break; + case 3: + /* Load 24 bits and add the padding bit to the 25th bit */ + subterranean_duplex_word + (state, ((uint32_t)(data[0]) | + (((uint32_t)(data[1])) << 8) | + (((uint32_t)(data[2])) << 16) | + 0x01000000U)); + break; + default: + /* Load 32 bits and add the padding bit to the 33rd bit */ + subterranean_duplex_word(state, le_load_word32(data)); + state->x[8] ^= 0x00000001U; + break; + } +} + +uint32_t subterranean_extract(subterranean_state_t *state) +{ + uint32_t x, y; + + /* We need to extract 64 bits from the state, and then XOR the two + * halves together to get the result. + * + * Extract words from the state and permute the bits into the target + * bit order. Then mask off the unnecessary bits and combine. + * + * Permutations generated with "http://programming.sirrida.de/calcperm.php". + */ + + /* P0 = [* 0 12 * 24 * * * 4 * * 17 * * * 14 16 30 * * * * 29 7 * * * * * * 26 *] */ + x = state->x[0]; + x = (x & 0x00010000U) + | ((x & 0x00000800U) << 6) + | ((x & 0x00400000U) << 7) + | ((x & 0x00000004U) << 10) + | ((x & 0x00020000U) << 13) + | ((x & 0x00800000U) >> 16) + | ((x & 0x00000010U) << 20) + | ((x & 0x40000100U) >> 4) + | ((x & 0x00008002U) >> 1); + y = x & 0x65035091U; + + /* P1 = [28 * 10 3 * * * * * * * * 9 * 19 * * * * * * * * * * * * * 6 * * *] */ + x = state->x[1]; + x = (x & 0x00000008U) + | ((x & 0x00004000U) << 5) + | ((x & 0x00000004U) << 8) + | ((x & 0x10000000U) >> 22) + | ((x & 0x00000001U) << 28) + | ((x & 0x00001000U) >> 3); + y ^= x & 0x10080648U; + + /* P2 = [8 * * 25 22 * 15 * * 11 * * * * * * * 1 * * * * * * 21 * * * 31 * * 13] */ + x = state->x[2]; + x = ((x & 0x00000200U) << 2) + | ((x & 0x10000000U) << 3) + | ((x & 0x00000001U) << 8) + | ((x & 0x00000040U) << 9) + | ((x & 0x80000000U) >> 18) + | ((x & 0x00020000U) >> 16) + | ((x & 0x00000010U) << 18) + | ((x & 0x00000008U) << 22) + | ((x & 0x01000000U) >> 3); + y ^= x & 0x8260a902U; + + /* P3 = [* * * * * * * * * * * * * * * 23 * * * * * 27 * * 18 2 * 5 * * * *] */ + x = state->x[3]; + x = ((x & 0x00200000U) << 6) + | ((x & 0x00008000U) << 8) + | ((x & 0x02000000U) >> 23) + | ((x & 0x08000000U) >> 22) + | ((x & 0x01000000U) >> 6); + y ^= x & 0x08840024U; + + /* P4 = [20 20 * * * * 5 * 2 18 * * 27 * * * * * 23 * * * * * * * * * * * * *] */ + x = state->x[4]; + y ^= (x << 20) & 0x00100000U; /* Handle duplicated bit 20 separately */ + x = ((x & 0x00040000U) << 5) + | ((x & 0x00000200U) << 9) + | ((x & 0x00001000U) << 15) + | ((x & 0x00000002U) << 19) + | ((x & 0x00000100U) >> 6) + | ((x & 0x00000040U) >> 1); + y ^= x & 0x08940024U; + + /* P5 = [* * 13 * * 31 * * * 21 * * * * * * 1 * * * * * * * 11 * * 15 * 22 25 *] */ + x = state->x[5]; + x = ((x & 0x00000004U) << 11) + | ((x & 0x00000200U) << 12) + | ((x & 0x00010000U) >> 15) + | ((x & 0x01000000U) >> 13) + | ((x & 0x08000000U) >> 12) + | ((x & 0x20000000U) >> 7) + | ((x & 0x00000020U) << 26) + | ((x & 0x40000000U) >> 5); + y ^= x & 0x8260a802U; + + /* P6 = [* 8 * * * 6 * * * * * * * * * * * * * 19 * 9 * * * * * * * * 3 10] */ + x = state->x[6]; + x = (x & 0x00080000U) + | ((x & 0x00000020U) << 1) + | ((x & 0x40000000U) >> 27) + | ((x & 0x00000002U) << 7) + | ((x & 0x80000000U) >> 21) + | ((x & 0x00200000U) >> 12); + y ^= x & 0x00080748U; + + /* P7 = [* 28 * 26 * * * * * * 7 29 * * * * 30 16 14 * * * 17 * * 4 * * * 24 * 12] */ + x = state->x[7]; + x = ((x & 0x02000000U) >> 21) + | ((x & 0x80000000U) >> 19) + | ((x & 0x00010000U) << 14) + | ((x & 0x00000800U) << 18) + | ((x & 0x00000008U) << 23) + | leftRotate27(x & 0x20400002U) + | ((x & 0x00040000U) >> 4) + | ((x & 0x00000400U) >> 3) + | ((x & 0x00020000U) >> 1); + y ^= x & 0x75035090U; + + /* Word 8 has a single bit - XOR it directly into the result and return */ + return y ^ state->x[8]; +} + +void subterranean_absorb + (subterranean_state_t *state, const unsigned char *data, + unsigned long long len) +{ + while (len >= 4) { + subterranean_duplex_4(state, data); + data += 4; + len -= 4; + } + subterranean_duplex_n(state, data, (unsigned)len); +} + +void subterranean_squeeze + (subterranean_state_t *state, unsigned char *data, unsigned len) +{ + uint32_t word; + while (len > 4) { + word = subterranean_extract(state); + subterranean_duplex_0(state); + le_store_word32(data, word); + data += 4; + len -= 4; + } + if (len == 4) { + word = subterranean_extract(state); + le_store_word32(data, word); + } else if (len == 1) { + word = subterranean_extract(state); + data[0] = (unsigned char)word; + } else if (len == 2) { + word = subterranean_extract(state); + data[0] = (unsigned char)word; + data[1] = (unsigned char)(word >> 8); + } else if (len == 3) { + word = subterranean_extract(state); + data[0] = (unsigned char)word; + data[1] = (unsigned char)(word >> 8); + data[2] = (unsigned char)(word >> 16); + } +} diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.h b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.h new file mode 100644 index 0000000..71cebb2 --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-subterranean.h @@ -0,0 +1,144 @@ +/* + * 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_SUBTERRANEAN_H +#define LW_INTERNAL_SUBTERRANEAN_H + +#include "internal-util.h" + +/** + * \file internal-subterranean.h + * \brief Internal implementation of the Subterranean block operation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Representation of the 257-bit state of Subterranean. + * + * The 257-bit state is represented as nine 32-bit words with only a single + * bit in the last word. + */ +typedef struct +{ + uint32_t x[9]; /**< State words */ + +} subterranean_state_t; + +/** + * \brief Performs a single Subterranean round. + * + * \param state Subterranean state to be transformed. + */ +void subterranean_round(subterranean_state_t *state); + +/** + * \brief Performs 8 Subterranean rounds with no absorption or squeezing + * of data; i.e. data input and output is "blanked". + * + * \param state Subterranean state to be transformed. + */ +void subterranean_blank(subterranean_state_t *state); + +/** + * \brief Performs a single Subterranean round and absorbs 0 bytes. + * + * \param state Subterranean state to be transformed. + */ +void subterranean_duplex_0(subterranean_state_t *state); + +/** + * \brief Performs a single Subterranean round and absorbs one byte. + * + * \param state Subterranean state to be transformed. + * \param data The single byte to be absorbed. + */ +void subterranean_duplex_1(subterranean_state_t *state, unsigned char data); + +/** + * \brief Absorbs a 32-bit word into the Subterranean state. + * + * \param state Subterranean state to be transformed. + * \param x The word to absorb into the state. + */ +void subterranean_duplex_word(subterranean_state_t *state, uint32_t x); + +/** + * \brief Performs a single Subterranean round and absorbs four bytes. + * + * \param state Subterranean state to be transformed. + * \param data Points to the four data bytes to be absorbed. + */ +#define subterranean_duplex_4(state, data) \ + do { \ + subterranean_duplex_word((state), le_load_word32((data))); \ + (state)->x[8] ^= 1; \ + } while (0) + +/** + * \brief Performs a single Subterranean round and absorbs between + * zero and four bytes. + * + * \param state Subterranean state to be transformed. + * \param data Points to the data bytes to be absorbed. + * \param len Length of the data to be absorbed. + */ +void subterranean_duplex_n + (subterranean_state_t *state, const unsigned char *data, unsigned len); + +/** + * \brief Extracts 32 bits of output from the Subterranean state. + * + * \param state Subterranean state to extract the output from. + * + * \return Returns the 32-bit word that was extracted. + */ +uint32_t subterranean_extract(subterranean_state_t *state); + +/** + * \brief Absorbs an arbitrary amount of data, four bytes at a time. + * + * \param state Subterranean state to be transformed. + * \param data Points to the bytes to be absorbed. + * \param len Number of bytes to absorb. + */ +void subterranean_absorb + (subterranean_state_t *state, const unsigned char *data, + unsigned long long len); + +/** + * \brief Squeezes an arbitrary amount of data out of a Subterranean state. + * + * \param state Subterranean state to extract the output from. + * \param data Points to the data buffer to receive the output. + * \param len Number of bytes to be extracted. + */ +void subterranean_squeeze + (subterranean_state_t *state, unsigned char *data, unsigned len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-util.h b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.c b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.c new file mode 100644 index 0000000..1bc9fc4 --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.c @@ -0,0 +1,228 @@ +/* + * 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 "subterranean.h" +#include "internal-subterranean.h" +#include + +aead_cipher_t const subterranean_cipher = { + "Subterranean", + SUBTERRANEAN_KEY_SIZE, + SUBTERRANEAN_NONCE_SIZE, + SUBTERRANEAN_TAG_SIZE, + AEAD_FLAG_NONE, + subterranean_aead_encrypt, + subterranean_aead_decrypt +}; + +aead_hash_algorithm_t const subterranean_hash_algorithm = { + "Subterranean-Hash", + sizeof(subterranean_hash_state_t), + SUBTERRANEAN_HASH_SIZE, + AEAD_FLAG_NONE, + subterranean_hash, + (aead_hash_init_t)subterranean_hash_init, + (aead_hash_update_t)subterranean_hash_update, + (aead_hash_finalize_t)subterranean_hash_finalize, + (aead_xof_absorb_t)0, + (aead_xof_squeeze_t)0 +}; + +int subterranean_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) +{ + subterranean_state_t state; + uint32_t x1, x2; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + SUBTERRANEAN_TAG_SIZE; + + /* Initialize the state and absorb the key and nonce */ + memset(&state, 0, sizeof(state)); + subterranean_absorb(&state, k, SUBTERRANEAN_KEY_SIZE); + subterranean_absorb(&state, npub, SUBTERRANEAN_NONCE_SIZE); + subterranean_blank(&state); + + /* Absorb the associated data into the state */ + subterranean_absorb(&state, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + while (mlen >= 4) { + x1 = le_load_word32(m); + x2 = subterranean_extract(&state) ^ x1; + subterranean_duplex_word(&state, x1); + state.x[8] ^= 1; /* padding for 32-bit blocks */ + le_store_word32(c, x2); + c += 4; + m += 4; + mlen -= 4; + } + switch ((unsigned char)mlen) { + default: + subterranean_duplex_0(&state); + break; + case 1: + x2 = subterranean_extract(&state) ^ m[0]; + subterranean_duplex_n(&state, m, 1); + c[0] = (unsigned char)x2; + break; + case 2: + x2 = subterranean_extract(&state) ^ m[0] ^ (((uint32_t)(m[1])) << 8); + subterranean_duplex_n(&state, m, 2); + c[0] = (unsigned char)x2; + c[1] = (unsigned char)(x2 >> 8); + break; + case 3: + x2 = subterranean_extract(&state) ^ + m[0] ^ (((uint32_t)(m[1])) << 8) ^ (((uint32_t)(m[2])) << 16); + subterranean_duplex_n(&state, m, 3); + c[0] = (unsigned char)x2; + c[1] = (unsigned char)(x2 >> 8); + c[2] = (unsigned char)(x2 >> 16); + break; + } + + /* Generate the authentication tag */ + subterranean_blank(&state); + subterranean_squeeze(&state, c + mlen, SUBTERRANEAN_TAG_SIZE); + return 0; +} + +int subterranean_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) +{ + subterranean_state_t state; + unsigned char *mtemp = m; + unsigned char tag[SUBTERRANEAN_TAG_SIZE]; + uint32_t x; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < SUBTERRANEAN_TAG_SIZE) + return -1; + *mlen = clen - SUBTERRANEAN_TAG_SIZE; + + /* Initialize the state and absorb the key and nonce */ + memset(&state, 0, sizeof(state)); + subterranean_absorb(&state, k, SUBTERRANEAN_KEY_SIZE); + subterranean_absorb(&state, npub, SUBTERRANEAN_NONCE_SIZE); + subterranean_blank(&state); + + /* Absorb the associated data into the state */ + subterranean_absorb(&state, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + clen -= SUBTERRANEAN_TAG_SIZE; + while (clen >= 4) { + x = le_load_word32(c); + x ^= subterranean_extract(&state); + subterranean_duplex_word(&state, x); + state.x[8] ^= 1; /* padding for 32-bit blocks */ + le_store_word32(m, x); + c += 4; + m += 4; + clen -= 4; + } + switch ((unsigned char)clen) { + default: + subterranean_duplex_0(&state); + break; + case 1: + m[0] = (unsigned char)(subterranean_extract(&state) ^ c[0]); + subterranean_duplex_1(&state, m[0]); + break; + case 2: + x = subterranean_extract(&state) ^ c[0] ^ (((uint32_t)(c[1])) << 8); + m[0] = (unsigned char)x; + m[1] = (unsigned char)(x >> 8); + subterranean_duplex_word(&state, (x & 0xFFFFU) | 0x10000U); + break; + case 3: + x = subterranean_extract(&state) ^ + c[0] ^ (((uint32_t)(c[1])) << 8) ^ (((uint32_t)(c[2])) << 16); + m[0] = (unsigned char)x; + m[1] = (unsigned char)(x >> 8); + m[2] = (unsigned char)(x >> 16); + subterranean_duplex_word(&state, (x & 0x00FFFFFFU) | 0x01000000U); + break; + } + + /* Check the authentication tag */ + subterranean_blank(&state); + subterranean_squeeze(&state, tag, sizeof(tag)); + return aead_check_tag(mtemp, *mlen, tag, c + clen, SUBTERRANEAN_TAG_SIZE); +} + +int subterranean_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + subterranean_state_t state; + memset(&state, 0, sizeof(state)); + while (inlen > 0) { + subterranean_duplex_1(&state, *in++); + subterranean_duplex_0(&state); + --inlen; + } + subterranean_duplex_0(&state); + subterranean_duplex_0(&state); + subterranean_blank(&state); + subterranean_squeeze(&state, out, SUBTERRANEAN_HASH_SIZE); + return 0; +} + +void subterranean_hash_init(subterranean_hash_state_t *state) +{ + memset(state, 0, sizeof(subterranean_hash_state_t)); +} + +void subterranean_hash_update + (subterranean_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + subterranean_state_t *st = (subterranean_state_t *)state; + while (inlen > 0) { + subterranean_duplex_1(st, *in++); + subterranean_duplex_0(st); + --inlen; + } +} + +void subterranean_hash_finalize + (subterranean_hash_state_t *state, unsigned char *out) +{ + subterranean_state_t *st = (subterranean_state_t *)state; + subterranean_duplex_0(st); + subterranean_duplex_0(st); + subterranean_blank(st); + subterranean_squeeze(st, out, SUBTERRANEAN_HASH_SIZE); +} diff --git a/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.h b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.h new file mode 100644 index 0000000..148e5e8 --- /dev/null +++ b/subterranean/Implementations/crypto_aead/subterraneanv1/rhys/subterranean.h @@ -0,0 +1,200 @@ +/* + * 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_SUBTERRANEAN_H +#define LWCRYPTO_SUBTERRANEAN_H + +#include "aead-common.h" + +/** + * \file subterranean.h + * \brief Subterranean authenticated encryption algorithm. + * + * Subterranean (technically "Subterranean 2.0") is a family of + * algorithms built around the 257-bit Subterranean permutation: + * + * \li Subterranean is an authenticated encryption algorithm with a 128-bit + * key, a 128-bit nonce, and a 128-bit tag. + * \li Subterranean-Hash is a hash algorithm with a 256-bit output. + * + * The Subterranean permutation is intended for hardware implementation. + * It is not structured for efficient software implementation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Subterranean. + */ +#define SUBTERRANEAN_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Subterranean. + */ +#define SUBTERRANEAN_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Subterranean. + */ +#define SUBTERRANEAN_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for Subterranean-Hash. + */ +#define SUBTERRANEAN_HASH_SIZE 32 + +/** + * \brief Meta-information block for the Subterranean cipher. + */ +extern aead_cipher_t const subterranean_cipher; + +/** + * \brief Meta-information block for the SUBTERRANEAN hash algorithm. + */ +extern aead_hash_algorithm_t const subterranean_hash_algorithm; + +/** + * \brief State information for the Subterreaan incremental hash mode. + */ +typedef union +{ + unsigned char state[40]; /**< Current hash state */ + unsigned long long align; /**< For alignment of this structure */ + +} subterranean_hash_state_t; + +/** + * \brief Encrypts and authenticates a packet with Subterranean. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa subterranean_aead_decrypt() + */ +int subterranean_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); + +/** + * \brief Decrypts and authenticates a packet with Subterranean. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa subterranean_aead_encrypt() + */ +int subterranean_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); + +/** + * \brief Hashes a block of input data with Subterranean. + * + * \param out Buffer to receive the hash output which must be at least + * SUBTERRANEAN_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. + * + * \sa subterranean_hash_init() + */ +int subterranean_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for a Subterranean hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa subterranean_hash_update(), subterranean_hash_finalize(), + * subterranean_hash() + */ +void subterranean_hash_init(subterranean_hash_state_t *state); + +/** + * \brief Updates a Subterranean 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. + * + * \sa subterranean_hash_init(), subterranean_hash_finalize() + */ +void subterranean_hash_update + (subterranean_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Returns the final hash value from a Subterranean hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the 32-byte hash value. + * + * \sa subterranean_hash_init(), subterranean_hash_update() + */ +void subterranean_hash_finalize + (subterranean_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.c b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.h b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/api.h b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/api.h new file mode 100644 index 0000000..4bd426b --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 0 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/encrypt.c b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/encrypt.c new file mode 100644 index 0000000..50af7fb --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sundae-gift.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 sundae_gift_0_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 sundae_gift_0_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.c b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.h b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-util.h b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.c b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.c new file mode 100644 index 0000000..984a4db --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.c @@ -0,0 +1,358 @@ +/* + * 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 "sundae-gift.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const sundae_gift_0_cipher = { + "SUNDAE-GIFT-0", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_0_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_0_aead_encrypt, + sundae_gift_0_aead_decrypt +}; + +aead_cipher_t const sundae_gift_64_cipher = { + "SUNDAE-GIFT-64", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_64_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_64_aead_encrypt, + sundae_gift_64_aead_decrypt +}; + +aead_cipher_t const sundae_gift_96_cipher = { + "SUNDAE-GIFT-96", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_96_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_96_aead_encrypt, + sundae_gift_96_aead_decrypt +}; + +aead_cipher_t const sundae_gift_128_cipher = { + "SUNDAE-GIFT-128", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_128_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_128_aead_encrypt, + sundae_gift_128_aead_decrypt +}; + +/* Multiply a block value by 2 in the special byte field */ +STATIC_INLINE void sundae_gift_multiply(unsigned char B[16]) +{ + unsigned char B0 = B[0]; + unsigned index; + for (index = 0; index < 15; ++index) + B[index] = B[index + 1]; + B[15] = B0; + B[10] ^= B0; + B[12] ^= B0; + B[14] ^= B0; +} + +/* Compute a MAC over the concatenation of two data buffers */ +static void sundae_gift_aead_mac + (const gift128b_key_schedule_t *ks, unsigned char V[16], + const unsigned char *data1, unsigned data1len, + const unsigned char *data2, unsigned long data2len) +{ + unsigned len; + + /* Nothing to do if the input is empty */ + if (!data1len && !data2len) + return; + + /* Format the first block. We assume that data1len <= 16 + * as it is will be the nonce if it is non-zero in length */ + lw_xor_block(V, data1, data1len); + len = 16 - data1len; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V + data1len, data2, len); + data2 += len; + data2len -= len; + len += data1len; + + /* Process as many full blocks as we can, except the last */ + while (data2len > 0) { + gift128b_encrypt(ks, V, V); + len = 16; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V, data2, len); + data2 += len; + data2len -= len; + } + + /* Pad and process the last block */ + if (len < 16) { + V[len] ^= 0x80; + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } else { + sundae_gift_multiply(V); + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } +} + +static int sundae_gift_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 *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char P[16]; + + /* Compute the length of the output ciphertext */ + *clen = mlen + SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (mlen > 0) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, T, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, T, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, T, 0, 0, m, mlen); + + /* Encrypt the plaintext to produce the ciphertext. We need to be + * careful how we manage the data because we could be doing in-place + * encryption. In SUNDAE-GIFT, the first 16 bytes of the ciphertext + * is the tag rather than the last 16 bytes in other algorithms. + * We need to swap the plaintext for the current block with the + * ciphertext or tag from the previous block */ + memcpy(V, T, 16); + while (mlen >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(P, V, m, 16); + memcpy(c, T, 16); + memcpy(T, P, 16); + c += 16; + m += 16; + mlen -= 16; + } + if (mlen > 0) { + unsigned leftover = (unsigned)mlen; + gift128b_encrypt(&ks, V, V); + lw_xor_block(V, m, leftover); + memcpy(c, T, 16); + memcpy(c + 16, V, leftover); + } else { + memcpy(c, T, 16); + } + return 0; +} + +static int sundae_gift_aead_decrypt + (unsigned char *m, unsigned long long *mlen, + const unsigned char *c, unsigned long long clen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char *mtemp; + unsigned long len; + + /* Bail out if the ciphertext is too short */ + if (clen < SUNDAE_GIFT_TAG_SIZE) + return -1; + len = *mlen = clen - SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Decrypt the ciphertext to produce the plaintext, using the + * tag as the initialization vector for the decryption process */ + memcpy(T, c, SUNDAE_GIFT_TAG_SIZE); + c += SUNDAE_GIFT_TAG_SIZE; + mtemp = m; + memcpy(V, T, 16); + while (len >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, 16); + c += 16; + mtemp += 16; + len -= 16; + } + if (len > 0) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, (unsigned)len); + } + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (clen > SUNDAE_GIFT_TAG_SIZE) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, V, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, V, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, V, 0, 0, m, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, T, V, 16); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.h b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.h new file mode 100644 index 0000000..9040dd5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift0v1/rhys/sundae-gift.h @@ -0,0 +1,341 @@ +/* + * 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_SUNDAE_GIFT_H +#define LWCRYPTO_SUNDAE_GIFT_H + +#include "aead-common.h" + +/** + * \file sundae-gift.h + * \brief SUNDAE-GIFT encryption algorithm family. + * + * The SUNDAE-GIFT family consists of several related algorithms: + * + * \li SUNDAE-GIFT-0 with a 128-bit key, a 0-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-64 with a 128-bit key, a 64-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-96 with a 128-bit key, a 96-bit nonce, and 128-bit tag. + * This is the primary member of the family. + * \li SUNDAE-GIFT-128 with a 128-bit key, a 128-bit nonce, and 128-bit tag. + * + * SUNDAE-GIFT is resistant against nonce reuse as long as the combination + * of the associated data and plaintext is unique. + * + * If a nonce is reused (or there is no nonce in the case of SUNDAE-GIFT-0), + * then two packets with the same associated data and plaintext will encrypt + * to the same ciphertext. This will leak that the same plaintext has been + * sent for a second time but will not reveal the plaintext itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-0. + */ +#define SUNDAE_GIFT_0_NONCE_SIZE 0 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-64. + */ +#define SUNDAE_GIFT_64_NONCE_SIZE 8 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-96. + */ +#define SUNDAE_GIFT_96_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-128. + */ +#define SUNDAE_GIFT_128_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SUNDAE-GIFT-0 cipher. + */ +extern aead_cipher_t const sundae_gift_0_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-64 cipher. + */ +extern aead_cipher_t const sundae_gift_64_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-96 cipher. + */ +extern aead_cipher_t const sundae_gift_96_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-128 cipher. + */ +extern aead_cipher_t const sundae_gift_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce - not used by this algorithm. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_0_aead_decrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 - not used by this algorithm. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_0_aead_encrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_64_aead_decrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_64_aead_encrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_96_aead_decrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_96_aead_encrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_128_aead_decrypt() + */ +int sundae_gift_128_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-12896. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_128_aead_encrypt() + */ +int sundae_gift_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.c b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.h b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/api.h b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/encrypt.c b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/encrypt.c new file mode 100644 index 0000000..b177c18 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sundae-gift.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 sundae_gift_128_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 sundae_gift_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.c b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.h b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-util.h b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.c b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.c new file mode 100644 index 0000000..984a4db --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.c @@ -0,0 +1,358 @@ +/* + * 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 "sundae-gift.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const sundae_gift_0_cipher = { + "SUNDAE-GIFT-0", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_0_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_0_aead_encrypt, + sundae_gift_0_aead_decrypt +}; + +aead_cipher_t const sundae_gift_64_cipher = { + "SUNDAE-GIFT-64", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_64_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_64_aead_encrypt, + sundae_gift_64_aead_decrypt +}; + +aead_cipher_t const sundae_gift_96_cipher = { + "SUNDAE-GIFT-96", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_96_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_96_aead_encrypt, + sundae_gift_96_aead_decrypt +}; + +aead_cipher_t const sundae_gift_128_cipher = { + "SUNDAE-GIFT-128", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_128_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_128_aead_encrypt, + sundae_gift_128_aead_decrypt +}; + +/* Multiply a block value by 2 in the special byte field */ +STATIC_INLINE void sundae_gift_multiply(unsigned char B[16]) +{ + unsigned char B0 = B[0]; + unsigned index; + for (index = 0; index < 15; ++index) + B[index] = B[index + 1]; + B[15] = B0; + B[10] ^= B0; + B[12] ^= B0; + B[14] ^= B0; +} + +/* Compute a MAC over the concatenation of two data buffers */ +static void sundae_gift_aead_mac + (const gift128b_key_schedule_t *ks, unsigned char V[16], + const unsigned char *data1, unsigned data1len, + const unsigned char *data2, unsigned long data2len) +{ + unsigned len; + + /* Nothing to do if the input is empty */ + if (!data1len && !data2len) + return; + + /* Format the first block. We assume that data1len <= 16 + * as it is will be the nonce if it is non-zero in length */ + lw_xor_block(V, data1, data1len); + len = 16 - data1len; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V + data1len, data2, len); + data2 += len; + data2len -= len; + len += data1len; + + /* Process as many full blocks as we can, except the last */ + while (data2len > 0) { + gift128b_encrypt(ks, V, V); + len = 16; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V, data2, len); + data2 += len; + data2len -= len; + } + + /* Pad and process the last block */ + if (len < 16) { + V[len] ^= 0x80; + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } else { + sundae_gift_multiply(V); + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } +} + +static int sundae_gift_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 *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char P[16]; + + /* Compute the length of the output ciphertext */ + *clen = mlen + SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (mlen > 0) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, T, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, T, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, T, 0, 0, m, mlen); + + /* Encrypt the plaintext to produce the ciphertext. We need to be + * careful how we manage the data because we could be doing in-place + * encryption. In SUNDAE-GIFT, the first 16 bytes of the ciphertext + * is the tag rather than the last 16 bytes in other algorithms. + * We need to swap the plaintext for the current block with the + * ciphertext or tag from the previous block */ + memcpy(V, T, 16); + while (mlen >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(P, V, m, 16); + memcpy(c, T, 16); + memcpy(T, P, 16); + c += 16; + m += 16; + mlen -= 16; + } + if (mlen > 0) { + unsigned leftover = (unsigned)mlen; + gift128b_encrypt(&ks, V, V); + lw_xor_block(V, m, leftover); + memcpy(c, T, 16); + memcpy(c + 16, V, leftover); + } else { + memcpy(c, T, 16); + } + return 0; +} + +static int sundae_gift_aead_decrypt + (unsigned char *m, unsigned long long *mlen, + const unsigned char *c, unsigned long long clen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char *mtemp; + unsigned long len; + + /* Bail out if the ciphertext is too short */ + if (clen < SUNDAE_GIFT_TAG_SIZE) + return -1; + len = *mlen = clen - SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Decrypt the ciphertext to produce the plaintext, using the + * tag as the initialization vector for the decryption process */ + memcpy(T, c, SUNDAE_GIFT_TAG_SIZE); + c += SUNDAE_GIFT_TAG_SIZE; + mtemp = m; + memcpy(V, T, 16); + while (len >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, 16); + c += 16; + mtemp += 16; + len -= 16; + } + if (len > 0) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, (unsigned)len); + } + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (clen > SUNDAE_GIFT_TAG_SIZE) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, V, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, V, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, V, 0, 0, m, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, T, V, 16); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.h b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.h new file mode 100644 index 0000000..9040dd5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift128v1/rhys/sundae-gift.h @@ -0,0 +1,341 @@ +/* + * 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_SUNDAE_GIFT_H +#define LWCRYPTO_SUNDAE_GIFT_H + +#include "aead-common.h" + +/** + * \file sundae-gift.h + * \brief SUNDAE-GIFT encryption algorithm family. + * + * The SUNDAE-GIFT family consists of several related algorithms: + * + * \li SUNDAE-GIFT-0 with a 128-bit key, a 0-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-64 with a 128-bit key, a 64-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-96 with a 128-bit key, a 96-bit nonce, and 128-bit tag. + * This is the primary member of the family. + * \li SUNDAE-GIFT-128 with a 128-bit key, a 128-bit nonce, and 128-bit tag. + * + * SUNDAE-GIFT is resistant against nonce reuse as long as the combination + * of the associated data and plaintext is unique. + * + * If a nonce is reused (or there is no nonce in the case of SUNDAE-GIFT-0), + * then two packets with the same associated data and plaintext will encrypt + * to the same ciphertext. This will leak that the same plaintext has been + * sent for a second time but will not reveal the plaintext itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-0. + */ +#define SUNDAE_GIFT_0_NONCE_SIZE 0 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-64. + */ +#define SUNDAE_GIFT_64_NONCE_SIZE 8 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-96. + */ +#define SUNDAE_GIFT_96_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-128. + */ +#define SUNDAE_GIFT_128_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SUNDAE-GIFT-0 cipher. + */ +extern aead_cipher_t const sundae_gift_0_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-64 cipher. + */ +extern aead_cipher_t const sundae_gift_64_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-96 cipher. + */ +extern aead_cipher_t const sundae_gift_96_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-128 cipher. + */ +extern aead_cipher_t const sundae_gift_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce - not used by this algorithm. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_0_aead_decrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 - not used by this algorithm. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_0_aead_encrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_64_aead_decrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_64_aead_encrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_96_aead_decrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_96_aead_encrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_128_aead_decrypt() + */ +int sundae_gift_128_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-12896. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_128_aead_encrypt() + */ +int sundae_gift_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.c b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.h b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/api.h b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/api.h new file mode 100644 index 0000000..6656888 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 8 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/encrypt.c b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/encrypt.c new file mode 100644 index 0000000..c6f2a7d --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sundae-gift.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 sundae_gift_64_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 sundae_gift_64_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.c b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.h b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-util.h b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.c b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.c new file mode 100644 index 0000000..984a4db --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.c @@ -0,0 +1,358 @@ +/* + * 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 "sundae-gift.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const sundae_gift_0_cipher = { + "SUNDAE-GIFT-0", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_0_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_0_aead_encrypt, + sundae_gift_0_aead_decrypt +}; + +aead_cipher_t const sundae_gift_64_cipher = { + "SUNDAE-GIFT-64", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_64_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_64_aead_encrypt, + sundae_gift_64_aead_decrypt +}; + +aead_cipher_t const sundae_gift_96_cipher = { + "SUNDAE-GIFT-96", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_96_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_96_aead_encrypt, + sundae_gift_96_aead_decrypt +}; + +aead_cipher_t const sundae_gift_128_cipher = { + "SUNDAE-GIFT-128", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_128_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_128_aead_encrypt, + sundae_gift_128_aead_decrypt +}; + +/* Multiply a block value by 2 in the special byte field */ +STATIC_INLINE void sundae_gift_multiply(unsigned char B[16]) +{ + unsigned char B0 = B[0]; + unsigned index; + for (index = 0; index < 15; ++index) + B[index] = B[index + 1]; + B[15] = B0; + B[10] ^= B0; + B[12] ^= B0; + B[14] ^= B0; +} + +/* Compute a MAC over the concatenation of two data buffers */ +static void sundae_gift_aead_mac + (const gift128b_key_schedule_t *ks, unsigned char V[16], + const unsigned char *data1, unsigned data1len, + const unsigned char *data2, unsigned long data2len) +{ + unsigned len; + + /* Nothing to do if the input is empty */ + if (!data1len && !data2len) + return; + + /* Format the first block. We assume that data1len <= 16 + * as it is will be the nonce if it is non-zero in length */ + lw_xor_block(V, data1, data1len); + len = 16 - data1len; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V + data1len, data2, len); + data2 += len; + data2len -= len; + len += data1len; + + /* Process as many full blocks as we can, except the last */ + while (data2len > 0) { + gift128b_encrypt(ks, V, V); + len = 16; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V, data2, len); + data2 += len; + data2len -= len; + } + + /* Pad and process the last block */ + if (len < 16) { + V[len] ^= 0x80; + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } else { + sundae_gift_multiply(V); + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } +} + +static int sundae_gift_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 *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char P[16]; + + /* Compute the length of the output ciphertext */ + *clen = mlen + SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (mlen > 0) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, T, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, T, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, T, 0, 0, m, mlen); + + /* Encrypt the plaintext to produce the ciphertext. We need to be + * careful how we manage the data because we could be doing in-place + * encryption. In SUNDAE-GIFT, the first 16 bytes of the ciphertext + * is the tag rather than the last 16 bytes in other algorithms. + * We need to swap the plaintext for the current block with the + * ciphertext or tag from the previous block */ + memcpy(V, T, 16); + while (mlen >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(P, V, m, 16); + memcpy(c, T, 16); + memcpy(T, P, 16); + c += 16; + m += 16; + mlen -= 16; + } + if (mlen > 0) { + unsigned leftover = (unsigned)mlen; + gift128b_encrypt(&ks, V, V); + lw_xor_block(V, m, leftover); + memcpy(c, T, 16); + memcpy(c + 16, V, leftover); + } else { + memcpy(c, T, 16); + } + return 0; +} + +static int sundae_gift_aead_decrypt + (unsigned char *m, unsigned long long *mlen, + const unsigned char *c, unsigned long long clen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char *mtemp; + unsigned long len; + + /* Bail out if the ciphertext is too short */ + if (clen < SUNDAE_GIFT_TAG_SIZE) + return -1; + len = *mlen = clen - SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Decrypt the ciphertext to produce the plaintext, using the + * tag as the initialization vector for the decryption process */ + memcpy(T, c, SUNDAE_GIFT_TAG_SIZE); + c += SUNDAE_GIFT_TAG_SIZE; + mtemp = m; + memcpy(V, T, 16); + while (len >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, 16); + c += 16; + mtemp += 16; + len -= 16; + } + if (len > 0) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, (unsigned)len); + } + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (clen > SUNDAE_GIFT_TAG_SIZE) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, V, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, V, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, V, 0, 0, m, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, T, V, 16); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.h b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.h new file mode 100644 index 0000000..9040dd5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift64v1/rhys/sundae-gift.h @@ -0,0 +1,341 @@ +/* + * 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_SUNDAE_GIFT_H +#define LWCRYPTO_SUNDAE_GIFT_H + +#include "aead-common.h" + +/** + * \file sundae-gift.h + * \brief SUNDAE-GIFT encryption algorithm family. + * + * The SUNDAE-GIFT family consists of several related algorithms: + * + * \li SUNDAE-GIFT-0 with a 128-bit key, a 0-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-64 with a 128-bit key, a 64-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-96 with a 128-bit key, a 96-bit nonce, and 128-bit tag. + * This is the primary member of the family. + * \li SUNDAE-GIFT-128 with a 128-bit key, a 128-bit nonce, and 128-bit tag. + * + * SUNDAE-GIFT is resistant against nonce reuse as long as the combination + * of the associated data and plaintext is unique. + * + * If a nonce is reused (or there is no nonce in the case of SUNDAE-GIFT-0), + * then two packets with the same associated data and plaintext will encrypt + * to the same ciphertext. This will leak that the same plaintext has been + * sent for a second time but will not reveal the plaintext itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-0. + */ +#define SUNDAE_GIFT_0_NONCE_SIZE 0 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-64. + */ +#define SUNDAE_GIFT_64_NONCE_SIZE 8 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-96. + */ +#define SUNDAE_GIFT_96_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-128. + */ +#define SUNDAE_GIFT_128_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SUNDAE-GIFT-0 cipher. + */ +extern aead_cipher_t const sundae_gift_0_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-64 cipher. + */ +extern aead_cipher_t const sundae_gift_64_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-96 cipher. + */ +extern aead_cipher_t const sundae_gift_96_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-128 cipher. + */ +extern aead_cipher_t const sundae_gift_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce - not used by this algorithm. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_0_aead_decrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 - not used by this algorithm. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_0_aead_encrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_64_aead_decrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_64_aead_encrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_96_aead_decrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_96_aead_encrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_128_aead_decrypt() + */ +int sundae_gift_128_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-12896. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_128_aead_encrypt() + */ +int sundae_gift_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.c b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.h b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/api.h b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/api.h new file mode 100644 index 0000000..c3c0a27 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/encrypt.c b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/encrypt.c new file mode 100644 index 0000000..a358142 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "sundae-gift.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 sundae_gift_96_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 sundae_gift_96_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.c b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.c new file mode 100644 index 0000000..681dbc8 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.c @@ -0,0 +1,849 @@ +/* + * 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 "internal-gift128.h" +#include "internal-util.h" + +/* Round constants for GIFT-128 in the fixsliced representation */ +static uint32_t const GIFT128_RC[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, 0x8000001f, 0x10888880, + 0x6001e000, 0x51500002, 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, 0x4001e000, 0x11500002, + 0x03020180, 0x8000002b, 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, 0x03010180, 0x8000002e, + 0x10088800, 0x60012000, 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/** + * \brief Swaps bits within two words. + * + * \param a The first word. + * \param b The second word. + * \param mask Mask for the bits to shift. + * \param shift Shift amount in bits. + */ +#define gift128b_swap_move(a, b, mask, shift) \ + do { \ + uint32_t tmp = ((b) ^ ((a) >> (shift))) & (mask); \ + (b) ^= tmp; \ + (a) ^= tmp << (shift); \ + } while (0) + +/** + * \brief Derives the next 10 fixsliced keys in the key schedule. + * + * \param next Points to the buffer to receive the next 10 keys. + * \param prev Points to the buffer holding the previous 10 keys. + * + * The \a next and \a prev buffers are allowed to be the same. + */ +#define gift128b_derive_keys(next, prev) \ + do { \ + /* Key 0 */ \ + uint32_t s = (prev)[0]; \ + uint32_t t = (prev)[1]; \ + gift128b_swap_move(t, t, 0x00003333U, 16); \ + gift128b_swap_move(t, t, 0x55554444U, 1); \ + (next)[0] = t; \ + /* Key 1 */ \ + s = leftRotate8(s & 0x33333333U) | leftRotate16(s & 0xCCCCCCCCU); \ + gift128b_swap_move(s, s, 0x55551100U, 1); \ + (next)[1] = s; \ + /* Key 2 */ \ + s = (prev)[2]; \ + t = (prev)[3]; \ + (next)[2] = ((t >> 4) & 0x0F000F00U) | ((t & 0x0F000F00U) << 4) | \ + ((t >> 6) & 0x00030003U) | ((t & 0x003F003FU) << 2); \ + /* Key 3 */ \ + (next)[3] = ((s >> 6) & 0x03000300U) | ((s & 0x3F003F00U) << 2) | \ + ((s >> 5) & 0x00070007U) | ((s & 0x001F001FU) << 3); \ + /* Key 4 */ \ + s = (prev)[4]; \ + t = (prev)[5]; \ + (next)[4] = leftRotate8(t & 0xAAAAAAAAU) | \ + leftRotate16(t & 0x55555555U); \ + /* Key 5 */ \ + (next)[5] = leftRotate8(s & 0x55555555U) | \ + leftRotate12(s & 0xAAAAAAAAU); \ + /* Key 6 */ \ + s = (prev)[6]; \ + t = (prev)[7]; \ + (next)[6] = ((t >> 2) & 0x03030303U) | ((t & 0x03030303U) << 2) | \ + ((t >> 1) & 0x70707070U) | ((t & 0x10101010U) << 3); \ + /* Key 7 */ \ + (next)[7] = ((s >> 18) & 0x00003030U) | ((s & 0x01010101U) << 3) | \ + ((s >> 14) & 0x0000C0C0U) | ((s & 0x0000E0E0U) << 15) | \ + ((s >> 1) & 0x07070707U) | ((s & 0x00001010U) << 19); \ + /* Key 8 */ \ + s = (prev)[8]; \ + t = (prev)[9]; \ + (next)[8] = ((t >> 4) & 0x0FFF0000U) | ((t & 0x000F0000U) << 12) | \ + ((t >> 8) & 0x000000FFU) | ((t & 0x000000FFU) << 8); \ + /* Key 9 */ \ + (next)[9] = ((s >> 6) & 0x03FF0000U) | ((s & 0x003F0000U) << 10) | \ + ((s >> 4) & 0x00000FFFU) | ((s & 0x0000000FU) << 12); \ + } while (0) + +/** + * \brief Compute the round keys for GIFT-128 in the fixsliced representation. + * + * \param ks Points to the key schedule to initialize. + * \param k0 First key word. + * \param k1 Second key word. + * \param k2 Third key word. + * \param k3 Fourth key word. + */ +static void gift128b_compute_round_keys + (gift128b_key_schedule_t *ks, + uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) +{ + unsigned index; + uint32_t temp; + + /* Set the regular key with k0 and k3 pre-swapped for the round function */ + ks->k[0] = k3; + ks->k[1] = k1; + ks->k[2] = k2; + ks->k[3] = k0; + + /* Pre-compute the keys for rounds 3..10 and permute into fixsliced form */ + for (index = 4; index < 20; index += 2) { + ks->k[index] = ks->k[index - 3]; + temp = ks->k[index - 4]; + temp = ((temp & 0xFFFC0000U) >> 2) | ((temp & 0x00030000U) << 14) | + ((temp & 0x00000FFFU) << 4) | ((temp & 0x0000F000U) >> 12); + ks->k[index + 1] = temp; + } + for (index = 0; index < 20; index += 10) { + /* Keys 0 and 10 */ + temp = ks->k[index]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index] = temp; + + /* Keys 1 and 11 */ + temp = ks->k[index + 1]; + gift128b_swap_move(temp, temp, 0x00550055U, 9); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 1] = temp; + + /* Keys 2 and 12 */ + temp = ks->k[index + 2]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 2] = temp; + + /* Keys 3 and 13 */ + temp = ks->k[index + 3]; + gift128b_swap_move(temp, temp, 0x11111111U, 3); + gift128b_swap_move(temp, temp, 0x03030303U, 6); + gift128b_swap_move(temp, temp, 0x000F000FU, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 3] = temp; + + /* Keys 4 and 14 */ + temp = ks->k[index + 4]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 4] = temp; + + /* Keys 5 and 15 */ + temp = ks->k[index + 5]; + gift128b_swap_move(temp, temp, 0x0000AAAAU, 15); + gift128b_swap_move(temp, temp, 0x00003333U, 18); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 5] = temp; + + /* Keys 6 and 16 */ + temp = ks->k[index + 6]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 6] = temp; + + /* Keys 7 and 17 */ + temp = ks->k[index + 7]; + gift128b_swap_move(temp, temp, 0x0A0A0A0AU, 3); + gift128b_swap_move(temp, temp, 0x00CC00CCU, 6); + gift128b_swap_move(temp, temp, 0x0000F0F0U, 12); + gift128b_swap_move(temp, temp, 0x000000FFU, 24); + ks->k[index + 7] = temp; + + /* Keys 8, 9, 18, and 19 do not need any adjustment */ + } + + /* Derive the fixsliced keys for the remaining rounds 11..40 */ + for (index = 20; index < 80; index += 10) { + gift128b_derive_keys(ks->k + index, ks->k + index - 20); + } +} + +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, be_load_word32(key), be_load_word32(key + 4), + be_load_word32(key + 8), be_load_word32(key + 12)); + return 1; +} + +/** + * \brief Performs the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_sbox(s0, s1, s2, s3) \ + do { \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xFFFFFFFFU; \ + s2 ^= s0 & s1; \ + } while (0) + +/** + * \brief Performs the inverse of the GIFT-128 S-box on the bit-sliced state. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_sbox(s0, s1, s2, s3) \ + do { \ + s2 ^= s3 & s1; \ + s0 ^= 0xFFFFFFFFU; \ + s1 ^= s0; \ + s0 ^= s2; \ + s2 ^= s3 | s1; \ + s3 ^= s1 & s0; \ + s1 ^= s3 & s2; \ + } while (0) + +/** + * \brief Permutes the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 3) & 0x11111111U) | ((s2 & 0x77777777U) << 1); \ + s3 = ((s3 >> 1) & 0x77777777U) | ((s3 & 0x11111111U) << 3); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 4) & 0x0FFF0FFFU) | ((s0 & 0x000F000FU) << 12); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 12) & 0x000F000FU) | ((s2 & 0x0FFF0FFFU) << 4); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s3 = leftRotate16(s3); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 6) & 0x03030303U) | ((s0 & 0x3F3F3F3FU) << 2); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 2) & 0x3F3F3F3FU) | ((s2 & 0x03030303U) << 6); \ + } while (0); + +/** + * \brief Permutes the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = rightRotate8(s2); \ + s3 = leftRotate8(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 1st and 2nd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_1(s0, s1, s2, s3) \ + do { \ + s1 = ((s1 >> 2) & 0x33333333U) | ((s1 & 0x33333333U) << 2); \ + s2 = ((s2 >> 1) & 0x77777777U) | ((s2 & 0x11111111U) << 3); \ + s3 = ((s3 >> 3) & 0x11111111U) | ((s3 & 0x77777777U) << 1); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 2nd and 3rd mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_2(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 12) & 0x000F000FU) | ((s0 & 0x0FFF0FFFU) << 4); \ + s1 = ((s1 >> 8) & 0x00FF00FFU) | ((s1 & 0x00FF00FFU) << 8); \ + s2 = ((s2 >> 4) & 0x0FFF0FFFU) | ((s2 & 0x000F000FU) << 12); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 3rd and 4th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_3(s0, s1, s2, s3) \ + do { \ + gift128b_swap_move(s1, s1, 0x55555555U, 1); \ + gift128b_swap_move(s2, s2, 0x00005555U, 1); \ + s2 = leftRotate16(s2); \ + gift128b_swap_move(s3, s3, 0x55550000U, 1); \ + s3 = leftRotate16(s3); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 4th and 5th mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_4(s0, s1, s2, s3) \ + do { \ + s0 = ((s0 >> 2) & 0x3F3F3F3FU) | ((s0 & 0x03030303U) << 6); \ + s1 = ((s1 >> 4) & 0x0F0F0F0FU) | ((s1 & 0x0F0F0F0FU) << 4); \ + s2 = ((s2 >> 6) & 0x03030303U) | ((s2 & 0x3F3F3F3FU) << 2); \ + } while (0); + +/** + * \brief Inverts the GIFT-128 state between the 5th and 1st mini-rounds. + * + * \param s0 First word of the bit-sliced state. + * \param s1 Second word of the bit-sliced state. + * \param s2 Third word of the bit-sliced state. + * \param s3 Fourth word of the bit-sliced state. + */ +#define gift128b_inv_permute_state_5(s0, s1, s2, s3) \ + do { \ + s1 = leftRotate16(s1); \ + s2 = leftRotate8(s2); \ + s3 = rightRotate8(s3); \ + } while (0); + +/** + * \brief Performs five fixsliced encryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + * + * The permutation is restructured so that one of the words each round + * does not need to be permuted, with the others rotating left, up, right, + * and down to keep the bits in line with their non-moving counterparts. + * This reduces the number of shifts required significantly. + * + * At the end of five rounds, the bit ordering will return to the + * original position. We then repeat the process for the next 5 rounds. + */ +#define gift128b_encrypt_5_rounds(rk, rc) \ + do { \ + /* 1st round - S-box, rotate left, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_1(s0, s1, s2, s3); \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + \ + /* 2nd round - S-box, rotate up, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_2(s0, s1, s2, s3); \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_3(s0, s1, s2, s3); \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + \ + /* 4th round - S-box, rotate left and swap rows, add round key */ \ + gift128b_sbox(s3, s1, s2, s0); \ + gift128b_permute_state_4(s0, s1, s2, s3); \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + \ + /* 5th round - S-box, rotate up, add round key */ \ + gift128b_sbox(s0, s1, s2, s3); \ + gift128b_permute_state_5(s0, s1, s2, s3); \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + \ + /* Swap s0 and s3 in preparation for the next 1st round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + } while (0) + +/** + * \brief Performs five fixsliced decryption rounds for GIFT-128. + * + * \param rk Points to the 10 round keys for these rounds. + * \param rc Points to the round constants for these rounds. + * + * We perform all 40 rounds of the fixsliced GIFT-128 five at a time. + */ +#define gift128b_decrypt_5_rounds(rk, rc) \ + do { \ + /* Swap s0 and s3 in preparation for the next 5th round */ \ + s0 ^= s3; \ + s3 ^= s0; \ + s0 ^= s3; \ + \ + /* 5th round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[8]; \ + s2 ^= (rk)[9]; \ + s0 ^= (rc)[4]; \ + gift128b_inv_permute_state_5(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 4th round - S-box, rotate right and swap rows, add round key */ \ + s1 ^= (rk)[6]; \ + s2 ^= (rk)[7]; \ + s3 ^= (rc)[3]; \ + gift128b_inv_permute_state_4(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 3rd round - S-box, swap columns, add round key */ \ + s1 ^= (rk)[4]; \ + s2 ^= (rk)[5]; \ + s0 ^= (rc)[2]; \ + gift128b_inv_permute_state_3(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + \ + /* 2nd round - S-box, rotate down, add round key */ \ + s1 ^= (rk)[2]; \ + s2 ^= (rk)[3]; \ + s3 ^= (rc)[1]; \ + gift128b_inv_permute_state_2(s0, s1, s2, s3); \ + gift128b_inv_sbox(s0, s1, s2, s3); \ + \ + /* 1st round - S-box, rotate right, add round key */ \ + s1 ^= (rk)[0]; \ + s2 ^= (rk)[1]; \ + s0 ^= (rc)[0]; \ + gift128b_inv_permute_state_1(s0, s1, s2, s3); \ + gift128b_inv_sbox(s3, s1, s2, s0); \ + } while (0) + +void gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into local variables */ + s0 = input[0]; + s1 = input[1]; + s2 = input[2]; + s3 = input[3]; + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer */ + output[0] = s0; + output[1] = s1; + output[2] = s2; + output[3] = s3; +} + +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Copy the plaintext into the state buffer and convert from big endian */ + s0 = be_load_word32(input); + s1 = be_load_word32(input + 4); + s2 = be_load_word32(input + 8); + s3 = be_load_word32(input + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method */ + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the ciphertext buffer in big endian */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); +} + +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len) +{ + /* Use the little-endian key byte order from the HYENA submission */ + if (!ks || !key || key_len != 16) + return 0; + gift128b_compute_round_keys + (ks, le_load_word32(key + 12), le_load_word32(key + 8), + le_load_word32(key + 4), le_load_word32(key)); + return 1; +} + +/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */ +#define bit_permute_step(_y, mask, shift) \ + do { \ + uint32_t y = (_y); \ + uint32_t t = ((y >> (shift)) ^ y) & (mask); \ + (_y) = (y ^ t) ^ (t << (shift)); \ + } while (0) + +/** + * \brief Converts the GIFT-128 nibble-based representation into word-based. + * + * \param output Output buffer to write the word-based version to. + * \param input Input buffer to read the nibble-based version from. + * + * The \a input and \a output buffers can be the same buffer. + */ +static void gift128n_to_words + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input buffer into 32-bit words. We use the nibble order + * from the HYENA submission to NIST which is byte-reversed with respect + * to the nibble order of the original GIFT-128 paper. Nibble zero is in + * the first byte instead of the last, which means little-endian order. */ + s0 = le_load_word32(input + 12); + s1 = le_load_word32(input + 8); + s2 = le_load_word32(input + 4); + s3 = le_load_word32(input); + + /* Rearrange the bits so that bits 0..3 of each nibble are + * scattered to bytes 0..3 of each word. The permutation is: + * + * 0 8 16 24 1 9 17 25 2 10 18 26 3 11 19 27 4 12 20 28 5 13 21 29 6 14 22 30 7 15 23 31 + * + * Generated with "http://programming.sirrida.de/calcperm.php". + */ + #define PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x0a0a0a0a, 3); \ + bit_permute_step(x, 0x00cc00cc, 6); \ + bit_permute_step(x, 0x0000f0f0, 12); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + PERM_WORDS(s0); + PERM_WORDS(s1); + PERM_WORDS(s2); + PERM_WORDS(s3); + + /* Rearrange the bytes and write them to the output buffer */ + output[0] = (uint8_t)s0; + output[1] = (uint8_t)s1; + output[2] = (uint8_t)s2; + output[3] = (uint8_t)s3; + output[4] = (uint8_t)(s0 >> 8); + output[5] = (uint8_t)(s1 >> 8); + output[6] = (uint8_t)(s2 >> 8); + output[7] = (uint8_t)(s3 >> 8); + output[8] = (uint8_t)(s0 >> 16); + output[9] = (uint8_t)(s1 >> 16); + output[10] = (uint8_t)(s2 >> 16); + output[11] = (uint8_t)(s3 >> 16); + output[12] = (uint8_t)(s0 >> 24); + output[13] = (uint8_t)(s1 >> 24); + output[14] = (uint8_t)(s2 >> 24); + output[15] = (uint8_t)(s3 >> 24); +} + +/** + * \brief Converts the GIFT-128 word-based representation into nibble-based. + * + * \param output Output buffer to write the nibble-based version to. + * \param input Input buffer to read the word-based version from. + */ +static void gift128n_to_nibbles + (unsigned char *output, const unsigned char *input) +{ + uint32_t s0, s1, s2, s3; + + /* Load the input bytes and rearrange them so that s0 contains the + * most significant nibbles and s3 contains the least significant */ + s0 = (((uint32_t)(input[12])) << 24) | + (((uint32_t)(input[8])) << 16) | + (((uint32_t)(input[4])) << 8) | + ((uint32_t)(input[0])); + s1 = (((uint32_t)(input[13])) << 24) | + (((uint32_t)(input[9])) << 16) | + (((uint32_t)(input[5])) << 8) | + ((uint32_t)(input[1])); + s2 = (((uint32_t)(input[14])) << 24) | + (((uint32_t)(input[10])) << 16) | + (((uint32_t)(input[6])) << 8) | + ((uint32_t)(input[2])); + s3 = (((uint32_t)(input[15])) << 24) | + (((uint32_t)(input[11])) << 16) | + (((uint32_t)(input[7])) << 8) | + ((uint32_t)(input[3])); + + /* Apply the inverse of PERM_WORDS() from the function above */ + #define INV_PERM_WORDS(_x) \ + do { \ + uint32_t x = (_x); \ + bit_permute_step(x, 0x00aa00aa, 7); \ + bit_permute_step(x, 0x0000cccc, 14); \ + bit_permute_step(x, 0x00f000f0, 4); \ + bit_permute_step(x, 0x0000ff00, 8); \ + (_x) = x; \ + } while (0) + INV_PERM_WORDS(s0); + INV_PERM_WORDS(s1); + INV_PERM_WORDS(s2); + INV_PERM_WORDS(s3); + + /* Store the result into the output buffer as 32-bit words */ + le_store_word32(output + 12, s0); + le_store_word32(output + 8, s1); + le_store_word32(output + 4, s2); + le_store_word32(output, s3); +} + +void gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_encrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input) +{ + gift128n_to_words(output, input); + gift128b_decrypt(ks, output, output); + gift128n_to_nibbles(output, output); +} + +/* 4-bit tweak values expanded to 32-bit */ +static uint32_t const GIFT128_tweaks[16] = { + 0x00000000, 0xe1e1e1e1, 0xd2d2d2d2, 0x33333333, + 0xb4b4b4b4, 0x55555555, 0x66666666, 0x87878787, + 0x78787878, 0x99999999, 0xaaaaaaaa, 0x4b4b4b4b, + 0xcccccccc, 0x2d2d2d2d, 0x1e1e1e1e, 0xffffffff +}; + +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the plaintext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the last we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_encrypt_5_rounds(ks->k, GIFT128_RC); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_encrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + + /* Pack the state into the ciphertext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} + +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak) +{ + uint32_t s0, s1, s2, s3, tword; + + /* Copy the ciphertext into the state buffer and convert from nibbles */ + gift128n_to_words(output, input); + s0 = be_load_word32(output); + s1 = be_load_word32(output + 4); + s2 = be_load_word32(output + 8); + s3 = be_load_word32(output + 12); + + /* Perform all 40 rounds five at a time using the fixsliced method. + * Every 5 rounds except the first we add the tweak value to the state */ + tword = GIFT128_tweaks[tweak]; + gift128b_decrypt_5_rounds(ks->k + 70, GIFT128_RC + 35); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 60, GIFT128_RC + 30); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 50, GIFT128_RC + 25); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 40, GIFT128_RC + 20); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 30, GIFT128_RC + 15); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 20, GIFT128_RC + 10); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k + 10, GIFT128_RC + 5); + s0 ^= tword; + gift128b_decrypt_5_rounds(ks->k, GIFT128_RC); + + /* Pack the state into the plaintext buffer in nibble form */ + be_store_word32(output, s0); + be_store_word32(output + 4, s1); + be_store_word32(output + 8, s2); + be_store_word32(output + 12, s3); + gift128n_to_nibbles(output, output); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.h b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.h new file mode 100644 index 0000000..1ac40e5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-gift128.h @@ -0,0 +1,229 @@ +/* + * 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_GIFT128_H +#define LW_INTERNAL_GIFT128_H + +/** + * \file internal-gift128.h + * \brief GIFT-128 block cipher. + * + * There are three versions of GIFT-128 in use within the second round + * submissions to the NIST lightweight cryptography competition. + * + * The most efficient version for 32-bit software implementation is the + * GIFT-128-b bit-sliced version from GIFT-COFB and SUNDAE-GIFT. + * + * The second is the nibble-based version from HYENA. We implement the + * HYENA version as a wrapper around the bit-sliced version. + * + * The third version is a variant on the HYENA nibble-based version that + * includes a 4-bit tweak value for domain separation. It is used by + * the ESTATE submission to NIST. + * + * Technically there is a fourth version of GIFT-128 which is the one that + * appeared in the original GIFT-128 paper. It is almost the same as the + * HYENA version except that the byte ordering is big-endian instead of + * HYENA's little-endian. The original version of GIFT-128 doesn't appear + * in any of the NIST submissions so we don't bother with it in this library. + * + * References: https://eprint.iacr.org/2017/622.pdf, + * https://giftcipher.github.io/gift/ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of a GIFT-128 block in bytes. + */ +#define GIFT128_BLOCK_SIZE 16 + +/** + * \brief Number of round keys for the fixsliced representation of GIFT-128. + */ +#define GIFT128_ROUND_KEYS 80 + +/** + * \brief Structure of the key schedule for GIFT-128 (bit-sliced). + */ +typedef struct +{ + /** Pre-computed round keys in the fixsliced form */ + uint32_t k[GIFT128_ROUND_KEYS]; + +} gift128b_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (bit-sliced). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128b_init + (gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 gift128b_encrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced and pre-loaded). + * + * \param ks Points to the GIFT-128 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. + * + * This version assumes that the input has already been pre-loaded from + * big-endian into host byte order in the supplied word array. The output + * is delivered in the same way. + */ +void gift128b_encrypt_preloaded + (const gift128b_key_schedule_t *ks, uint32_t output[4], + const uint32_t input[4]); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (bit-sliced). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128b_decrypt + (const gift128b_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Structure of the key schedule for GIFT-128 (nibble-based). + */ +typedef gift128b_key_schedule_t gift128n_key_schedule_t; + +/** + * \brief Initializes the key schedule for GIFT-128 (nibble-based). + * + * \param ks Points to the key schedule to initialize. + * \param key Points to the key data. + * \param key_len Length of the key data, which must be 16. + * + * \return Non-zero on success or zero if there is something wrong + * with the parameters. + */ +int gift128n_init + (gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len); + +/** + * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 gift128n_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Decrypts a 128-bit block with GIFT-128 (nibble-based). + * + * \param ks Points to the GIFT-128 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 decryption. + */ +void gift128n_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input); + +/** + * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_encrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +/** + * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). + * + * \param ks Points to the GIFT-128 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 tweak 4-bit tweak value. + * + * The \a input and \a output buffers can be the same buffer for + * in-place encryption. + * + * This variant of GIFT-128 is used by the ESTATE submission to the + * NIST Lightweight Cryptography Competition. A 4-bit tweak is added to + * some of the rounds to provide domain separation. If the tweak is + * zero, then this function is identical to gift128n_encrypt(). + */ +void gift128t_decrypt + (const gift128n_key_schedule_t *ks, unsigned char *output, + const unsigned char *input, unsigned char tweak); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-util.h b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.c b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.c new file mode 100644 index 0000000..984a4db --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.c @@ -0,0 +1,358 @@ +/* + * 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 "sundae-gift.h" +#include "internal-gift128.h" +#include "internal-util.h" +#include + +aead_cipher_t const sundae_gift_0_cipher = { + "SUNDAE-GIFT-0", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_0_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_0_aead_encrypt, + sundae_gift_0_aead_decrypt +}; + +aead_cipher_t const sundae_gift_64_cipher = { + "SUNDAE-GIFT-64", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_64_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_64_aead_encrypt, + sundae_gift_64_aead_decrypt +}; + +aead_cipher_t const sundae_gift_96_cipher = { + "SUNDAE-GIFT-96", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_96_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_96_aead_encrypt, + sundae_gift_96_aead_decrypt +}; + +aead_cipher_t const sundae_gift_128_cipher = { + "SUNDAE-GIFT-128", + SUNDAE_GIFT_KEY_SIZE, + SUNDAE_GIFT_128_NONCE_SIZE, + SUNDAE_GIFT_TAG_SIZE, + AEAD_FLAG_NONE, + sundae_gift_128_aead_encrypt, + sundae_gift_128_aead_decrypt +}; + +/* Multiply a block value by 2 in the special byte field */ +STATIC_INLINE void sundae_gift_multiply(unsigned char B[16]) +{ + unsigned char B0 = B[0]; + unsigned index; + for (index = 0; index < 15; ++index) + B[index] = B[index + 1]; + B[15] = B0; + B[10] ^= B0; + B[12] ^= B0; + B[14] ^= B0; +} + +/* Compute a MAC over the concatenation of two data buffers */ +static void sundae_gift_aead_mac + (const gift128b_key_schedule_t *ks, unsigned char V[16], + const unsigned char *data1, unsigned data1len, + const unsigned char *data2, unsigned long data2len) +{ + unsigned len; + + /* Nothing to do if the input is empty */ + if (!data1len && !data2len) + return; + + /* Format the first block. We assume that data1len <= 16 + * as it is will be the nonce if it is non-zero in length */ + lw_xor_block(V, data1, data1len); + len = 16 - data1len; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V + data1len, data2, len); + data2 += len; + data2len -= len; + len += data1len; + + /* Process as many full blocks as we can, except the last */ + while (data2len > 0) { + gift128b_encrypt(ks, V, V); + len = 16; + if (len > data2len) + len = (unsigned)data2len; + lw_xor_block(V, data2, len); + data2 += len; + data2len -= len; + } + + /* Pad and process the last block */ + if (len < 16) { + V[len] ^= 0x80; + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } else { + sundae_gift_multiply(V); + sundae_gift_multiply(V); + gift128b_encrypt(ks, V, V); + } +} + +static int sundae_gift_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 *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char P[16]; + + /* Compute the length of the output ciphertext */ + *clen = mlen + SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (mlen > 0) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, T, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, T, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, T, 0, 0, m, mlen); + + /* Encrypt the plaintext to produce the ciphertext. We need to be + * careful how we manage the data because we could be doing in-place + * encryption. In SUNDAE-GIFT, the first 16 bytes of the ciphertext + * is the tag rather than the last 16 bytes in other algorithms. + * We need to swap the plaintext for the current block with the + * ciphertext or tag from the previous block */ + memcpy(V, T, 16); + while (mlen >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(P, V, m, 16); + memcpy(c, T, 16); + memcpy(T, P, 16); + c += 16; + m += 16; + mlen -= 16; + } + if (mlen > 0) { + unsigned leftover = (unsigned)mlen; + gift128b_encrypt(&ks, V, V); + lw_xor_block(V, m, leftover); + memcpy(c, T, 16); + memcpy(c + 16, V, leftover); + } else { + memcpy(c, T, 16); + } + return 0; +} + +static int sundae_gift_aead_decrypt + (unsigned char *m, unsigned long long *mlen, + const unsigned char *c, unsigned long long clen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub, unsigned npublen, + const unsigned char *k, unsigned char domainsep) +{ + gift128b_key_schedule_t ks; + unsigned char V[16]; + unsigned char T[16]; + unsigned char *mtemp; + unsigned long len; + + /* Bail out if the ciphertext is too short */ + if (clen < SUNDAE_GIFT_TAG_SIZE) + return -1; + len = *mlen = clen - SUNDAE_GIFT_TAG_SIZE; + + /* Set the key schedule */ + if (!gift128b_init(&ks, k, SUNDAE_GIFT_KEY_SIZE)) + return -1; + + /* Decrypt the ciphertext to produce the plaintext, using the + * tag as the initialization vector for the decryption process */ + memcpy(T, c, SUNDAE_GIFT_TAG_SIZE); + c += SUNDAE_GIFT_TAG_SIZE; + mtemp = m; + memcpy(V, T, 16); + while (len >= 16) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, 16); + c += 16; + mtemp += 16; + len -= 16; + } + if (len > 0) { + gift128b_encrypt(&ks, V, V); + lw_xor_block_2_src(mtemp, c, V, (unsigned)len); + } + + /* Format and encrypt the initial domain separation block */ + if (adlen > 0) + domainsep |= 0x80; + if (clen > SUNDAE_GIFT_TAG_SIZE) + domainsep |= 0x40; + V[0] = domainsep; + memset(V + 1, 0, sizeof(V) - 1); + gift128b_encrypt(&ks, V, V); + + /* Authenticate the nonce and the associated data */ + sundae_gift_aead_mac(&ks, V, npub, npublen, ad, adlen); + + /* Authenticate the plaintext */ + sundae_gift_aead_mac(&ks, V, 0, 0, m, *mlen); + + /* Check the authentication tag */ + return aead_check_tag(m, *mlen, T, V, 16); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_0_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) +{ + (void)nsec; + (void)npub; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, 0, 0, k, 0x00); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_64_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_64_NONCE_SIZE, k, 0x90); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_96_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_96_NONCE_SIZE, k, 0xA0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_encrypt + (c, clen, m, mlen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} + +int sundae_gift_128_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) +{ + (void)nsec; + return sundae_gift_aead_decrypt + (m, mlen, c, clen, ad, adlen, + npub, SUNDAE_GIFT_128_NONCE_SIZE, k, 0xB0); +} diff --git a/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.h b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.h new file mode 100644 index 0000000..9040dd5 --- /dev/null +++ b/sundae-gift/Implementations/crypto_aead/sundaegift96v1/rhys/sundae-gift.h @@ -0,0 +1,341 @@ +/* + * 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_SUNDAE_GIFT_H +#define LWCRYPTO_SUNDAE_GIFT_H + +#include "aead-common.h" + +/** + * \file sundae-gift.h + * \brief SUNDAE-GIFT encryption algorithm family. + * + * The SUNDAE-GIFT family consists of several related algorithms: + * + * \li SUNDAE-GIFT-0 with a 128-bit key, a 0-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-64 with a 128-bit key, a 64-bit nonce, and 128-bit tag. + * \li SUNDAE-GIFT-96 with a 128-bit key, a 96-bit nonce, and 128-bit tag. + * This is the primary member of the family. + * \li SUNDAE-GIFT-128 with a 128-bit key, a 128-bit nonce, and 128-bit tag. + * + * SUNDAE-GIFT is resistant against nonce reuse as long as the combination + * of the associated data and plaintext is unique. + * + * If a nonce is reused (or there is no nonce in the case of SUNDAE-GIFT-0), + * then two packets with the same associated data and plaintext will encrypt + * to the same ciphertext. This will leak that the same plaintext has been + * sent for a second time but will not reveal the plaintext itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for all SUNDAE-GIFT family members. + */ +#define SUNDAE_GIFT_TAG_SIZE 16 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-0. + */ +#define SUNDAE_GIFT_0_NONCE_SIZE 0 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-64. + */ +#define SUNDAE_GIFT_64_NONCE_SIZE 8 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-96. + */ +#define SUNDAE_GIFT_96_NONCE_SIZE 12 + +/** + * \brief Size of the nonce for SUNDAE-GIFT-128. + */ +#define SUNDAE_GIFT_128_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the SUNDAE-GIFT-0 cipher. + */ +extern aead_cipher_t const sundae_gift_0_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-64 cipher. + */ +extern aead_cipher_t const sundae_gift_64_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-96 cipher. + */ +extern aead_cipher_t const sundae_gift_96_cipher; + +/** + * \brief Meta-information block for the SUNDAE-GIFT-128 cipher. + */ +extern aead_cipher_t const sundae_gift_128_cipher; + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce - not used by this algorithm. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_0_aead_decrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-0. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 - not used by this algorithm. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_0_aead_encrypt() + */ +int sundae_gift_0_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_64_aead_decrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-64. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 8 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_64_aead_encrypt() + */ +int sundae_gift_64_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_96_aead_decrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-96. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_96_aead_encrypt() + */ +int sundae_gift_96_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); + +/** + * \brief Encrypts and authenticates a packet with SUNDAE-GIFT-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa sundae_gift_128_aead_decrypt() + */ +int sundae_gift_128_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); + +/** + * \brief Decrypts and authenticates a packet with SUNDAE-GIFT-12896. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa sundae_gift_128_aead_encrypt() + */ +int sundae_gift_128_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.c b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.h b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/api.h b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/api.h new file mode 100644 index 0000000..32c9622 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/encrypt.c b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/encrypt.c new file mode 100644 index 0000000..832ac67 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "tinyjambu.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 tiny_jambu_128_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 tiny_jambu_128_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.c new file mode 100644 index 0000000..7308718 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.c @@ -0,0 +1,66 @@ +/* + * 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 "internal-tinyjambu.h" + +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds) +{ + uint32_t t1, t2, t3, t4; + unsigned round; + + /* Load the state into local variables */ + uint32_t s0 = state[0]; + uint32_t s1 = state[1]; + uint32_t s2 = state[2]; + uint32_t s3 = state[3]; + + /* Perform all permutation rounds. Each round consists of 128 steps, + * which can be performed 32 at a time plus a rotation. After four + * sets of 32 steps, the rotation order returns to the original position. + * So we can hide the rotations by doing 128 steps each round */ + for (round = 0; round < rounds; ++round) { + /* Get the key words to use during this round */ + const uint32_t *k = &(key[(round * 4) % key_words]); + + /* Perform the 128 steps of this round in groups of 32 */ + #define tiny_jambu_steps_32(s0, s1, s2, s3, offset) \ + do { \ + t1 = (s1 >> 15) | (s2 << 17); \ + t2 = (s2 >> 6) | (s3 << 26); \ + t3 = (s2 >> 21) | (s3 << 11); \ + t4 = (s2 >> 27) | (s3 << 5); \ + s0 ^= t1 ^ (~(t2 & t3)) ^ t4 ^ k[offset]; \ + } while (0) + tiny_jambu_steps_32(s0, s1, s2, s3, 0); + tiny_jambu_steps_32(s1, s2, s3, s0, 1); + tiny_jambu_steps_32(s2, s3, s0, s1, 2); + tiny_jambu_steps_32(s3, s0, s1, s2, 3); + } + + /* Store the local variables back to the state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.h new file mode 100644 index 0000000..f3bc599 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-tinyjambu.h @@ -0,0 +1,72 @@ +/* + * 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_TINYJAMBU_H +#define LW_INTERNAL_TINYJAMBU_H + +#include "internal-util.h" + +/** + * \file internal-tinyjambu.h + * \brief Internal implementation of the TinyJAMBU permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the TinyJAMBU state in 32-bit words. + */ +#define TINY_JAMBU_STATE_SIZE 4 + +/** + * \brief Converts a number of steps into a number of rounds, where each + * round consists of 128 steps. + * + * \param steps The number of steps to perform; 384, 1024, 1152, or 1280. + * + * \return The number of rounds corresponding to \a steps. + */ +#define TINYJAMBU_ROUNDS(steps) ((steps) / 128) + +/** + * \brief Perform the TinyJAMBU permutation. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform. + * + * The number of key words should be 4 for TinyJAMBU-128, 12 for TinyJAMBU-192, + * and 8 for TinuJAMBU-256. The TinyJAMBU-192 key is duplicated so that the + * \a key_words parameter is a multiple of 4. + */ +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-util.h b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.c new file mode 100644 index 0000000..09fc41d --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.c @@ -0,0 +1,487 @@ +/* + * 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 "tinyjambu.h" +#include "internal-tinyjambu.h" +#include + +aead_cipher_t const tiny_jambu_128_cipher = { + "TinyJAMBU-128", + TINY_JAMBU_128_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_128_aead_encrypt, + tiny_jambu_128_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_192_cipher = { + "TinyJAMBU-192", + TINY_JAMBU_192_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_192_aead_encrypt, + tiny_jambu_192_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_256_cipher = { + "TinyJAMBU-256", + TINY_JAMBU_256_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_256_aead_encrypt, + tiny_jambu_256_aead_decrypt +}; + +/** + * \brief Set up the TinyJAMBU state with the key and the nonce. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to absorb the key. + * \param nonce Points to the nonce. + * + * \sa tiny_jambu_permutation() + */ +static void tiny_jambu_setup + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, const unsigned char *nonce) +{ + /* Initialize the state with the key */ + memset(state, 0, TINY_JAMBU_STATE_SIZE * sizeof(uint32_t)); + tiny_jambu_permutation(state, key, key_words, rounds); + + /* Absorb the three 32-bit words of the 96-bit nonce */ + state[1] ^= 0x10; /* Domain separator for the nonce */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 4); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 8); +} + +/** + * \brief Processes the associated data for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void tiny_jambu_process_ad + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, const unsigned char *ad, unsigned long long adlen) +{ + /* Process as many full 32-bit words as we can */ + while (adlen >= 4) { + state[1] ^= 0x30; /* Domain separator for associated data */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(ad); + ad += 4; + adlen -= 4; + } + + /* Handle the left-over associated data bytes, if any */ + if (adlen == 1) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= ad[0]; + state[1] ^= 0x01; + } else if (adlen == 2) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad); + state[1] ^= 0x02; + } else if (adlen == 3) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad) | (((uint32_t)(ad[2])) << 16); + state[1] ^= 0x03; + } +} + +/** + * \brief Encrypts the plaintext with TinyJAMBU to produce the ciphertext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the plaintext. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_encrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(m); + state[3] ^= data; + data ^= state[2]; + le_store_word32(c, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over plaintext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = m[0]; + state[3] ^= data; + state[1] ^= 0x01; + c[0] = (uint8_t)(state[2] ^ data); + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m); + state[3] ^= data; + state[1] ^= 0x02; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m) | (((uint32_t)(m[2])) << 16); + state[3] ^= data; + state[1] ^= 0x03; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + c[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Decrypts the ciphertext with TinyJAMBU to produce the plaintext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the ciphertext. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_decrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(c) ^ state[2]; + state[3] ^= data; + le_store_word32(m, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over ciphertext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (c[0] ^ state[2]) & 0xFFU; + state[3] ^= data; + state[1] ^= 0x01; + m[0] = (uint8_t)data; + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (le_load_word16(c) ^ state[2]) & 0xFFFFU; + state[3] ^= data; + state[1] ^= 0x02; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(c) | (((uint32_t)(c[2])) << 16); + data = (data ^ state[2]) & 0xFFFFFFU; + state[3] ^= data; + state[1] ^= 0x03; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + m[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Generates the final authentication tag for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to generate the tag. + * \param tag Buffer to receive the tag. + */ +static void tiny_jambu_generate_tag + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *tag) +{ + state[1] ^= 0x70; /* Domain separator for finalization */ + tiny_jambu_permutation(state, key, key_words, rounds); + le_store_word32(tag, state[2]); + state[1] ^= 0x70; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + le_store_word32(tag + 4, state[2]); +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), c + mlen); + return 0; +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), c + mlen); + return 0; +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), c + mlen); + return 0; +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.h new file mode 100644 index 0000000..cb304ff --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu128/rhys/tinyjambu.h @@ -0,0 +1,270 @@ +/* + * 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_TINYJAMBU_H +#define LWCRYPTO_TINYJAMBU_H + +#include "aead-common.h" + +/** + * \file tinyjambu.h + * \brief TinyJAMBU authenticated encryption algorithm. + * + * TinyJAMBU is a family of encryption algorithms that are built around a + * lightweight 128-bit permutation. There are three variants of TinyJAMBU + * with different key sizes: + * + * \li TinyJAMBU-128 with a 128-bit key, a 96-bit nonce, and a 64-bit tag. + * This is the primary member of the family. + * \li TinyJAMBU-192 with a 192-bit key, a 96-bit nonce, and a 64-bit tag. + * \li TinyJAMBU-256 with a 256-bit key, a 96-bit nonce, and a 64-bit tag. + * + * TinyJAMBU has one of the smallest RAM and flash memory footprints + * out of all the algorithms in this library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for TinyJAMBU-128. + */ +#define TINY_JAMBU_128_KEY_SIZE 16 + +/** + * \brief Size of the key for TinyJAMBU-192. + */ +#define TINY_JAMBU_192_KEY_SIZE 24 + +/** + * \brief Size of the key for TinyJAMBU-256. + */ +#define TINY_JAMBU_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all TinyJAMBU variants. + */ +#define TINY_JAMBU_TAG_SIZE 8 + +/** + * \brief Size of the nonce for all TinyJAMBU variants. + */ +#define TINY_JAMBU_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the TinyJAMBU-128 cipher. + */ +extern aead_cipher_t const tiny_jambu_128_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-192 cipher. + */ +extern aead_cipher_t const tiny_jambu_192_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-256 cipher. + */ +extern aead_cipher_t const tiny_jambu_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_128_aead_decrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa tiny_jambu_128_aead_encrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_192_aead_decrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa tiny_jambu_192_aead_encrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_256_aead_decrypt() + */ +int tiny_jambu_256_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-256. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa tiny_jambu_256_aead_encrypt() + */ +int tiny_jambu_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.c b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.h b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/api.h b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/api.h new file mode 100644 index 0000000..1ee99ed --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 24 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/encrypt.c b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/encrypt.c new file mode 100644 index 0000000..62a5dde --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "tinyjambu.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 tiny_jambu_192_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 tiny_jambu_192_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.c new file mode 100644 index 0000000..7308718 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.c @@ -0,0 +1,66 @@ +/* + * 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 "internal-tinyjambu.h" + +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds) +{ + uint32_t t1, t2, t3, t4; + unsigned round; + + /* Load the state into local variables */ + uint32_t s0 = state[0]; + uint32_t s1 = state[1]; + uint32_t s2 = state[2]; + uint32_t s3 = state[3]; + + /* Perform all permutation rounds. Each round consists of 128 steps, + * which can be performed 32 at a time plus a rotation. After four + * sets of 32 steps, the rotation order returns to the original position. + * So we can hide the rotations by doing 128 steps each round */ + for (round = 0; round < rounds; ++round) { + /* Get the key words to use during this round */ + const uint32_t *k = &(key[(round * 4) % key_words]); + + /* Perform the 128 steps of this round in groups of 32 */ + #define tiny_jambu_steps_32(s0, s1, s2, s3, offset) \ + do { \ + t1 = (s1 >> 15) | (s2 << 17); \ + t2 = (s2 >> 6) | (s3 << 26); \ + t3 = (s2 >> 21) | (s3 << 11); \ + t4 = (s2 >> 27) | (s3 << 5); \ + s0 ^= t1 ^ (~(t2 & t3)) ^ t4 ^ k[offset]; \ + } while (0) + tiny_jambu_steps_32(s0, s1, s2, s3, 0); + tiny_jambu_steps_32(s1, s2, s3, s0, 1); + tiny_jambu_steps_32(s2, s3, s0, s1, 2); + tiny_jambu_steps_32(s3, s0, s1, s2, 3); + } + + /* Store the local variables back to the state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.h new file mode 100644 index 0000000..f3bc599 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-tinyjambu.h @@ -0,0 +1,72 @@ +/* + * 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_TINYJAMBU_H +#define LW_INTERNAL_TINYJAMBU_H + +#include "internal-util.h" + +/** + * \file internal-tinyjambu.h + * \brief Internal implementation of the TinyJAMBU permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the TinyJAMBU state in 32-bit words. + */ +#define TINY_JAMBU_STATE_SIZE 4 + +/** + * \brief Converts a number of steps into a number of rounds, where each + * round consists of 128 steps. + * + * \param steps The number of steps to perform; 384, 1024, 1152, or 1280. + * + * \return The number of rounds corresponding to \a steps. + */ +#define TINYJAMBU_ROUNDS(steps) ((steps) / 128) + +/** + * \brief Perform the TinyJAMBU permutation. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform. + * + * The number of key words should be 4 for TinyJAMBU-128, 12 for TinyJAMBU-192, + * and 8 for TinuJAMBU-256. The TinyJAMBU-192 key is duplicated so that the + * \a key_words parameter is a multiple of 4. + */ +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-util.h b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.c new file mode 100644 index 0000000..09fc41d --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.c @@ -0,0 +1,487 @@ +/* + * 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 "tinyjambu.h" +#include "internal-tinyjambu.h" +#include + +aead_cipher_t const tiny_jambu_128_cipher = { + "TinyJAMBU-128", + TINY_JAMBU_128_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_128_aead_encrypt, + tiny_jambu_128_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_192_cipher = { + "TinyJAMBU-192", + TINY_JAMBU_192_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_192_aead_encrypt, + tiny_jambu_192_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_256_cipher = { + "TinyJAMBU-256", + TINY_JAMBU_256_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_256_aead_encrypt, + tiny_jambu_256_aead_decrypt +}; + +/** + * \brief Set up the TinyJAMBU state with the key and the nonce. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to absorb the key. + * \param nonce Points to the nonce. + * + * \sa tiny_jambu_permutation() + */ +static void tiny_jambu_setup + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, const unsigned char *nonce) +{ + /* Initialize the state with the key */ + memset(state, 0, TINY_JAMBU_STATE_SIZE * sizeof(uint32_t)); + tiny_jambu_permutation(state, key, key_words, rounds); + + /* Absorb the three 32-bit words of the 96-bit nonce */ + state[1] ^= 0x10; /* Domain separator for the nonce */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 4); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 8); +} + +/** + * \brief Processes the associated data for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void tiny_jambu_process_ad + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, const unsigned char *ad, unsigned long long adlen) +{ + /* Process as many full 32-bit words as we can */ + while (adlen >= 4) { + state[1] ^= 0x30; /* Domain separator for associated data */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(ad); + ad += 4; + adlen -= 4; + } + + /* Handle the left-over associated data bytes, if any */ + if (adlen == 1) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= ad[0]; + state[1] ^= 0x01; + } else if (adlen == 2) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad); + state[1] ^= 0x02; + } else if (adlen == 3) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad) | (((uint32_t)(ad[2])) << 16); + state[1] ^= 0x03; + } +} + +/** + * \brief Encrypts the plaintext with TinyJAMBU to produce the ciphertext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the plaintext. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_encrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(m); + state[3] ^= data; + data ^= state[2]; + le_store_word32(c, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over plaintext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = m[0]; + state[3] ^= data; + state[1] ^= 0x01; + c[0] = (uint8_t)(state[2] ^ data); + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m); + state[3] ^= data; + state[1] ^= 0x02; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m) | (((uint32_t)(m[2])) << 16); + state[3] ^= data; + state[1] ^= 0x03; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + c[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Decrypts the ciphertext with TinyJAMBU to produce the plaintext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the ciphertext. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_decrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(c) ^ state[2]; + state[3] ^= data; + le_store_word32(m, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over ciphertext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (c[0] ^ state[2]) & 0xFFU; + state[3] ^= data; + state[1] ^= 0x01; + m[0] = (uint8_t)data; + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (le_load_word16(c) ^ state[2]) & 0xFFFFU; + state[3] ^= data; + state[1] ^= 0x02; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(c) | (((uint32_t)(c[2])) << 16); + data = (data ^ state[2]) & 0xFFFFFFU; + state[3] ^= data; + state[1] ^= 0x03; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + m[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Generates the final authentication tag for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to generate the tag. + * \param tag Buffer to receive the tag. + */ +static void tiny_jambu_generate_tag + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *tag) +{ + state[1] ^= 0x70; /* Domain separator for finalization */ + tiny_jambu_permutation(state, key, key_words, rounds); + le_store_word32(tag, state[2]); + state[1] ^= 0x70; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + le_store_word32(tag + 4, state[2]); +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), c + mlen); + return 0; +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), c + mlen); + return 0; +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), c + mlen); + return 0; +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.h new file mode 100644 index 0000000..cb304ff --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu192/rhys/tinyjambu.h @@ -0,0 +1,270 @@ +/* + * 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_TINYJAMBU_H +#define LWCRYPTO_TINYJAMBU_H + +#include "aead-common.h" + +/** + * \file tinyjambu.h + * \brief TinyJAMBU authenticated encryption algorithm. + * + * TinyJAMBU is a family of encryption algorithms that are built around a + * lightweight 128-bit permutation. There are three variants of TinyJAMBU + * with different key sizes: + * + * \li TinyJAMBU-128 with a 128-bit key, a 96-bit nonce, and a 64-bit tag. + * This is the primary member of the family. + * \li TinyJAMBU-192 with a 192-bit key, a 96-bit nonce, and a 64-bit tag. + * \li TinyJAMBU-256 with a 256-bit key, a 96-bit nonce, and a 64-bit tag. + * + * TinyJAMBU has one of the smallest RAM and flash memory footprints + * out of all the algorithms in this library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for TinyJAMBU-128. + */ +#define TINY_JAMBU_128_KEY_SIZE 16 + +/** + * \brief Size of the key for TinyJAMBU-192. + */ +#define TINY_JAMBU_192_KEY_SIZE 24 + +/** + * \brief Size of the key for TinyJAMBU-256. + */ +#define TINY_JAMBU_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all TinyJAMBU variants. + */ +#define TINY_JAMBU_TAG_SIZE 8 + +/** + * \brief Size of the nonce for all TinyJAMBU variants. + */ +#define TINY_JAMBU_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the TinyJAMBU-128 cipher. + */ +extern aead_cipher_t const tiny_jambu_128_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-192 cipher. + */ +extern aead_cipher_t const tiny_jambu_192_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-256 cipher. + */ +extern aead_cipher_t const tiny_jambu_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_128_aead_decrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa tiny_jambu_128_aead_encrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_192_aead_decrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa tiny_jambu_192_aead_encrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_256_aead_decrypt() + */ +int tiny_jambu_256_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-256. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa tiny_jambu_256_aead_encrypt() + */ +int tiny_jambu_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.c b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.h b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/api.h b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/api.h new file mode 100644 index 0000000..fd4ff9f --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 32 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 12 +#define CRYPTO_ABYTES 8 +#define CRYPTO_NOOVERLAP 1 diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/encrypt.c b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/encrypt.c new file mode 100644 index 0000000..357b9fe --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "tinyjambu.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 tiny_jambu_256_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 tiny_jambu_256_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.c new file mode 100644 index 0000000..7308718 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.c @@ -0,0 +1,66 @@ +/* + * 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 "internal-tinyjambu.h" + +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds) +{ + uint32_t t1, t2, t3, t4; + unsigned round; + + /* Load the state into local variables */ + uint32_t s0 = state[0]; + uint32_t s1 = state[1]; + uint32_t s2 = state[2]; + uint32_t s3 = state[3]; + + /* Perform all permutation rounds. Each round consists of 128 steps, + * which can be performed 32 at a time plus a rotation. After four + * sets of 32 steps, the rotation order returns to the original position. + * So we can hide the rotations by doing 128 steps each round */ + for (round = 0; round < rounds; ++round) { + /* Get the key words to use during this round */ + const uint32_t *k = &(key[(round * 4) % key_words]); + + /* Perform the 128 steps of this round in groups of 32 */ + #define tiny_jambu_steps_32(s0, s1, s2, s3, offset) \ + do { \ + t1 = (s1 >> 15) | (s2 << 17); \ + t2 = (s2 >> 6) | (s3 << 26); \ + t3 = (s2 >> 21) | (s3 << 11); \ + t4 = (s2 >> 27) | (s3 << 5); \ + s0 ^= t1 ^ (~(t2 & t3)) ^ t4 ^ k[offset]; \ + } while (0) + tiny_jambu_steps_32(s0, s1, s2, s3, 0); + tiny_jambu_steps_32(s1, s2, s3, s0, 1); + tiny_jambu_steps_32(s2, s3, s0, s1, 2); + tiny_jambu_steps_32(s3, s0, s1, s2, 3); + } + + /* Store the local variables back to the state */ + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.h new file mode 100644 index 0000000..f3bc599 --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-tinyjambu.h @@ -0,0 +1,72 @@ +/* + * 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_TINYJAMBU_H +#define LW_INTERNAL_TINYJAMBU_H + +#include "internal-util.h" + +/** + * \file internal-tinyjambu.h + * \brief Internal implementation of the TinyJAMBU permutation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the TinyJAMBU state in 32-bit words. + */ +#define TINY_JAMBU_STATE_SIZE 4 + +/** + * \brief Converts a number of steps into a number of rounds, where each + * round consists of 128 steps. + * + * \param steps The number of steps to perform; 384, 1024, 1152, or 1280. + * + * \return The number of rounds corresponding to \a steps. + */ +#define TINYJAMBU_ROUNDS(steps) ((steps) / 128) + +/** + * \brief Perform the TinyJAMBU permutation. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform. + * + * The number of key words should be 4 for TinyJAMBU-128, 12 for TinyJAMBU-192, + * and 8 for TinuJAMBU-256. The TinyJAMBU-192 key is duplicated so that the + * \a key_words parameter is a multiple of 4. + */ +void tiny_jambu_permutation + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-util.h b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.c b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.c new file mode 100644 index 0000000..09fc41d --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.c @@ -0,0 +1,487 @@ +/* + * 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 "tinyjambu.h" +#include "internal-tinyjambu.h" +#include + +aead_cipher_t const tiny_jambu_128_cipher = { + "TinyJAMBU-128", + TINY_JAMBU_128_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_128_aead_encrypt, + tiny_jambu_128_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_192_cipher = { + "TinyJAMBU-192", + TINY_JAMBU_192_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_192_aead_encrypt, + tiny_jambu_192_aead_decrypt +}; + +aead_cipher_t const tiny_jambu_256_cipher = { + "TinyJAMBU-256", + TINY_JAMBU_256_KEY_SIZE, + TINY_JAMBU_NONCE_SIZE, + TINY_JAMBU_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + tiny_jambu_256_aead_encrypt, + tiny_jambu_256_aead_decrypt +}; + +/** + * \brief Set up the TinyJAMBU state with the key and the nonce. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to absorb the key. + * \param nonce Points to the nonce. + * + * \sa tiny_jambu_permutation() + */ +static void tiny_jambu_setup + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, const unsigned char *nonce) +{ + /* Initialize the state with the key */ + memset(state, 0, TINY_JAMBU_STATE_SIZE * sizeof(uint32_t)); + tiny_jambu_permutation(state, key, key_words, rounds); + + /* Absorb the three 32-bit words of the 96-bit nonce */ + state[1] ^= 0x10; /* Domain separator for the nonce */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 4); + state[1] ^= 0x10; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(nonce + 8); +} + +/** + * \brief Processes the associated data for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param ad Points to the associated data. + * \param adlen Length of the associated data in bytes. + */ +static void tiny_jambu_process_ad + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, const unsigned char *ad, unsigned long long adlen) +{ + /* Process as many full 32-bit words as we can */ + while (adlen >= 4) { + state[1] ^= 0x30; /* Domain separator for associated data */ + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word32(ad); + ad += 4; + adlen -= 4; + } + + /* Handle the left-over associated data bytes, if any */ + if (adlen == 1) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= ad[0]; + state[1] ^= 0x01; + } else if (adlen == 2) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad); + state[1] ^= 0x02; + } else if (adlen == 3) { + state[1] ^= 0x30; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + state[3] ^= le_load_word16(ad) | (((uint32_t)(ad[2])) << 16); + state[1] ^= 0x03; + } +} + +/** + * \brief Encrypts the plaintext with TinyJAMBU to produce the ciphertext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the plaintext. + * \param c Points to the ciphertext output buffer. + * \param m Points to the plaintext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_encrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *c, + const unsigned char *m, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(m); + state[3] ^= data; + data ^= state[2]; + le_store_word32(c, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over plaintext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = m[0]; + state[3] ^= data; + state[1] ^= 0x01; + c[0] = (uint8_t)(state[2] ^ data); + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m); + state[3] ^= data; + state[1] ^= 0x02; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(m) | (((uint32_t)(m[2])) << 16); + state[3] ^= data; + state[1] ^= 0x03; + data ^= state[2]; + c[0] = (uint8_t)data; + c[1] = (uint8_t)(data >> 8); + c[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Decrypts the ciphertext with TinyJAMBU to produce the plaintext. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to process the ciphertext. + * \param m Points to the plaintext output buffer. + * \param c Points to the ciphertext input buffer. + * \param mlen Length of the plaintext in bytes. + */ +static void tiny_jambu_decrypt + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *m, + const unsigned char *c, unsigned long long mlen) +{ + uint32_t data; + + /* Process as many full 32-bit words as we can */ + while (mlen >= 4) { + state[1] ^= 0x50; /* Domain separator for message data */ + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word32(c) ^ state[2]; + state[3] ^= data; + le_store_word32(m, data); + c += 4; + m += 4; + mlen -= 4; + } + + /* Handle the left-over ciphertext data bytes, if any */ + if (mlen == 1) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (c[0] ^ state[2]) & 0xFFU; + state[3] ^= data; + state[1] ^= 0x01; + m[0] = (uint8_t)data; + } else if (mlen == 2) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = (le_load_word16(c) ^ state[2]) & 0xFFFFU; + state[3] ^= data; + state[1] ^= 0x02; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + } else if (mlen == 3) { + state[1] ^= 0x50; + tiny_jambu_permutation(state, key, key_words, rounds); + data = le_load_word16(c) | (((uint32_t)(c[2])) << 16); + data = (data ^ state[2]) & 0xFFFFFFU; + state[3] ^= data; + state[1] ^= 0x03; + m[0] = (uint8_t)data; + m[1] = (uint8_t)(data >> 8); + m[2] = (uint8_t)(data >> 16); + } +} + +/** + * \brief Generates the final authentication tag for TinyJAMBU. + * + * \param state TinyJAMBU state to be permuted. + * \param key Points to the key words. + * \param key_words The number of words in the key. + * \param rounds The number of rounds to perform to generate the tag. + * \param tag Buffer to receive the tag. + */ +static void tiny_jambu_generate_tag + (uint32_t state[TINY_JAMBU_STATE_SIZE], const uint32_t *key, + unsigned key_words, unsigned rounds, unsigned char *tag) +{ + state[1] ^= 0x70; /* Domain separator for finalization */ + tiny_jambu_permutation(state, key, key_words, rounds); + le_store_word32(tag, state[2]); + state[1] ^= 0x70; + tiny_jambu_permutation(state, key, key_words, TINYJAMBU_ROUNDS(384)); + le_store_word32(tag + 4, state[2]); +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), c + mlen); + return 0; +} + +int tiny_jambu_128_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[4]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 4, TINYJAMBU_ROUNDS(1024), npub); + tiny_jambu_process_ad(state, key, 4, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 4, TINYJAMBU_ROUNDS(1024), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 4, TINYJAMBU_ROUNDS(1024), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), c + mlen); + return 0; +} + +int tiny_jambu_192_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[12]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key and duplicate it to make the length a multiple of 4 */ + key[6] = key[0] = le_load_word32(k); + key[7] = key[1] = le_load_word32(k + 4); + key[8] = key[2] = le_load_word32(k + 8); + key[9] = key[3] = le_load_word32(k + 12); + key[10] = key[4] = le_load_word32(k + 16); + key[11] = key[5] = le_load_word32(k + 20); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 12, TINYJAMBU_ROUNDS(1152), npub); + tiny_jambu_process_ad(state, key, 12, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 12, TINYJAMBU_ROUNDS(1152), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 12, TINYJAMBU_ROUNDS(1152), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + tiny_jambu_encrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), c, m, mlen); + + /* Generate the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), c + mlen); + return 0; +} + +int tiny_jambu_256_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) +{ + uint32_t state[TINY_JAMBU_STATE_SIZE]; + uint32_t key[8]; + unsigned char tag[TINY_JAMBU_TAG_SIZE]; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < TINY_JAMBU_TAG_SIZE) + return -1; + *mlen = clen - TINY_JAMBU_TAG_SIZE; + + /* Unpack the key */ + key[0] = le_load_word32(k); + key[1] = le_load_word32(k + 4); + key[2] = le_load_word32(k + 8); + key[3] = le_load_word32(k + 12); + key[4] = le_load_word32(k + 16); + key[5] = le_load_word32(k + 20); + key[6] = le_load_word32(k + 24); + key[7] = le_load_word32(k + 28); + + /* Set up the TinyJAMBU state with the key, nonce, and associated data */ + tiny_jambu_setup(state, key, 8, TINYJAMBU_ROUNDS(1280), npub); + tiny_jambu_process_ad(state, key, 8, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + tiny_jambu_decrypt(state, key, 8, TINYJAMBU_ROUNDS(1280), m, c, *mlen); + + /* Check the authentication tag */ + tiny_jambu_generate_tag(state, key, 8, TINYJAMBU_ROUNDS(1280), tag); + return aead_check_tag(m, *mlen, tag, c + *mlen, TINY_JAMBU_TAG_SIZE); +} diff --git a/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.h b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.h new file mode 100644 index 0000000..cb304ff --- /dev/null +++ b/tinyjambu/Implementations/crypto_aead/tinyjambu256/rhys/tinyjambu.h @@ -0,0 +1,270 @@ +/* + * 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_TINYJAMBU_H +#define LWCRYPTO_TINYJAMBU_H + +#include "aead-common.h" + +/** + * \file tinyjambu.h + * \brief TinyJAMBU authenticated encryption algorithm. + * + * TinyJAMBU is a family of encryption algorithms that are built around a + * lightweight 128-bit permutation. There are three variants of TinyJAMBU + * with different key sizes: + * + * \li TinyJAMBU-128 with a 128-bit key, a 96-bit nonce, and a 64-bit tag. + * This is the primary member of the family. + * \li TinyJAMBU-192 with a 192-bit key, a 96-bit nonce, and a 64-bit tag. + * \li TinyJAMBU-256 with a 256-bit key, a 96-bit nonce, and a 64-bit tag. + * + * TinyJAMBU has one of the smallest RAM and flash memory footprints + * out of all the algorithms in this library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for TinyJAMBU-128. + */ +#define TINY_JAMBU_128_KEY_SIZE 16 + +/** + * \brief Size of the key for TinyJAMBU-192. + */ +#define TINY_JAMBU_192_KEY_SIZE 24 + +/** + * \brief Size of the key for TinyJAMBU-256. + */ +#define TINY_JAMBU_256_KEY_SIZE 32 + +/** + * \brief Size of the authentication tag for all TinyJAMBU variants. + */ +#define TINY_JAMBU_TAG_SIZE 8 + +/** + * \brief Size of the nonce for all TinyJAMBU variants. + */ +#define TINY_JAMBU_NONCE_SIZE 12 + +/** + * \brief Meta-information block for the TinyJAMBU-128 cipher. + */ +extern aead_cipher_t const tiny_jambu_128_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-192 cipher. + */ +extern aead_cipher_t const tiny_jambu_192_cipher; + +/** + * \brief Meta-information block for the TinyJAMBU-256 cipher. + */ +extern aead_cipher_t const tiny_jambu_256_cipher; + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-128. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_128_aead_decrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-128. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa tiny_jambu_128_aead_encrypt() + */ +int tiny_jambu_128_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-192. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_192_aead_decrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-192. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 24 bytes of 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. + * + * \sa tiny_jambu_192_aead_encrypt() + */ +int tiny_jambu_192_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); + +/** + * \brief Encrypts and authenticates a packet with TinyJAMBU-256. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 8 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa tiny_jambu_256_aead_decrypt() + */ +int tiny_jambu_256_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); + +/** + * \brief Decrypts and authenticates a packet with TinyJAMBU-256. + * + * \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 - not used by this algorithm. + * \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 8 byte 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 which must + * be 12 bytes in length. + * \param k Points to the 32 bytes of 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. + * + * \sa tiny_jambu_256_aead_encrypt() + */ +int tiny_jambu_256_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.c b/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.h b/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/api.h b/wage/Implementations/crypto_aead/wageae128v1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/encrypt.c b/wage/Implementations/crypto_aead/wageae128v1/rhys/encrypt.c new file mode 100644 index 0000000..0ed30f7 --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "wage.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 wage_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 wage_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-util.h b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.c b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.c new file mode 100644 index 0000000..e9528c9 --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.c @@ -0,0 +1,512 @@ +/* + * 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 "internal-wage.h" + +/** + * \brief Number of rounds for the WAGE permutation. + */ +#define WAGE_NUM_ROUNDS 111 + +/** + * \brief Define WAGE_64BIT to use the 64-bit version of the WAGE core + * permutation. Undefine to use the 8-bit version instead. + */ +#define WAGE_64BIT 1 + +/** + * \brief RC0 and RC1 round constants for WAGE, interleaved with each other. + */ +static unsigned char const wage_rc[WAGE_NUM_ROUNDS * 2] = { + 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x40, 0x20, 0x10, 0x08, 0x04, + 0x02, 0x41, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x43, 0x21, 0x50, 0x28, 0x14, + 0x0a, 0x45, 0x62, 0x71, 0x78, 0x3c, 0x1e, 0x4f, 0x27, 0x13, 0x09, 0x44, + 0x22, 0x51, 0x68, 0x34, 0x1a, 0x4d, 0x66, 0x73, 0x39, 0x5c, 0x2e, 0x57, + 0x2b, 0x15, 0x4a, 0x65, 0x72, 0x79, 0x7c, 0x3e, 0x5f, 0x2f, 0x17, 0x0b, + 0x05, 0x42, 0x61, 0x70, 0x38, 0x1c, 0x0e, 0x47, 0x23, 0x11, 0x48, 0x24, + 0x12, 0x49, 0x64, 0x32, 0x59, 0x6c, 0x36, 0x5b, 0x2d, 0x56, 0x6b, 0x35, + 0x5a, 0x6d, 0x76, 0x7b, 0x3d, 0x5e, 0x6f, 0x37, 0x1b, 0x0d, 0x46, 0x63, + 0x31, 0x58, 0x2c, 0x16, 0x4b, 0x25, 0x52, 0x69, 0x74, 0x3a, 0x5d, 0x6e, + 0x77, 0x3b, 0x1d, 0x4e, 0x67, 0x33, 0x19, 0x4c, 0x26, 0x53, 0x29, 0x54, + 0x2a, 0x55, 0x6a, 0x75, 0x7a, 0x7d, 0x7e, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, + 0x03, 0x01, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x41, 0x60, 0x30, 0x18, + 0x0c, 0x06, 0x43, 0x21, 0x50, 0x28, 0x14, 0x0a, 0x45, 0x62, 0x71, 0x78, + 0x3c, 0x1e, 0x4f, 0x27, 0x13, 0x09, 0x44, 0x22, 0x51, 0x68, 0x34, 0x1a, + 0x4d, 0x66, 0x73, 0x39, 0x5c, 0x2e, 0x57, 0x2b, 0x15, 0x4a, 0x65, 0x72, + 0x79, 0x7c, 0x3e, 0x5f, 0x2f, 0x17, 0x0b, 0x05, 0x42, 0x61, 0x70, 0x38, + 0x1c, 0x0e, 0x47, 0x23, 0x11, 0x48, 0x24, 0x12, 0x49, 0x64, 0x32, 0x59, + 0x6c, 0x36, 0x5b, 0x2d, 0x56, 0x6b, 0x35, 0x5a, 0x6d, 0x76, 0x7b, 0x3d, + 0x5e, 0x6f, 0x37, 0x1b, 0x0d, 0x46 +}; + +/** + * \brief Apply the WGP permutation to a 7-bit component. + * + * Warning: This is not constant cache. + */ +static unsigned char const wage_wgp[128] = { + 0x00, 0x12, 0x0a, 0x4b, 0x66, 0x0c, 0x48, 0x73, 0x79, 0x3e, 0x61, 0x51, + 0x01, 0x15, 0x17, 0x0e, 0x7e, 0x33, 0x68, 0x36, 0x42, 0x35, 0x37, 0x5e, + 0x53, 0x4c, 0x3f, 0x54, 0x58, 0x6e, 0x56, 0x2a, 0x1d, 0x25, 0x6d, 0x65, + 0x5b, 0x71, 0x2f, 0x20, 0x06, 0x18, 0x29, 0x3a, 0x0d, 0x7a, 0x6c, 0x1b, + 0x19, 0x43, 0x70, 0x41, 0x49, 0x22, 0x77, 0x60, 0x4f, 0x45, 0x55, 0x02, + 0x63, 0x47, 0x75, 0x2d, 0x40, 0x46, 0x7d, 0x5c, 0x7c, 0x59, 0x26, 0x0b, + 0x09, 0x03, 0x57, 0x5d, 0x27, 0x78, 0x30, 0x2e, 0x44, 0x52, 0x3b, 0x08, + 0x67, 0x2c, 0x05, 0x6b, 0x2b, 0x1a, 0x21, 0x38, 0x07, 0x0f, 0x4a, 0x11, + 0x50, 0x6a, 0x28, 0x31, 0x10, 0x4d, 0x5f, 0x72, 0x39, 0x16, 0x5a, 0x13, + 0x04, 0x3c, 0x34, 0x1f, 0x76, 0x1e, 0x14, 0x23, 0x1c, 0x32, 0x4e, 0x7b, + 0x24, 0x74, 0x7f, 0x3d, 0x69, 0x64, 0x62, 0x6f +}; + +/** + * \brief Evaluate the WAGE S-box three times in parallel. + * + * \param x6 The input values to the S-box. + * \return The output values from the S-box. + * + * This function directly evaluates the S-box in bit-sliced form + * using the algorithm from the specification. + */ +STATIC_INLINE uint32_t wage_sbox_parallel_3(uint32_t x6) +{ + uint32_t x0 = x6 >> 6; + uint32_t x1 = x6 >> 5; + uint32_t x2 = x6 >> 4; + uint32_t x3 = x6 >> 3; + uint32_t x4 = x6 >> 2; + uint32_t x5 = x6 >> 1; + x0 ^= (x2 & x3); x3 = ~x3; x3 ^= (x5 & x6); x5 = ~x5; x5 ^= (x2 & x4); + x6 ^= (x0 & x4); x4 = ~x4; x4 ^= (x5 & x1); x5 = ~x5; x5 ^= (x0 & x2); + x1 ^= (x6 & x2); x2 = ~x2; x2 ^= (x5 & x3); x5 = ~x5; x5 ^= (x6 & x0); + x3 ^= (x1 & x0); x0 = ~x0; x0 ^= (x5 & x4); x5 = ~x5; x5 ^= (x1 & x6); + x4 ^= (x3 & x6); x6 = ~x6; x6 ^= (x5 & x2); x5 = ~x5; x5 ^= (x3 & x1); + x2 ^= (x4 & x1); x1 = ~x1; x1 ^= (x5 & x0); x5 = ~x5; x5 ^= (x4 & x3); + x2 = ~x2; x4 = ~x4; + return ((x2 & 0x00010101U) << 6) ^ + ((x6 & 0x00010101U) << 5) ^ + ((x4 & 0x00010101U) << 4) ^ + ((x1 & 0x00010101U) << 3) ^ + ((x3 & 0x00010101U) << 2) ^ + ((x5 & 0x00010101U) << 1) ^ + (x0 & 0x00010101U); +} + +void wage_permute(unsigned char s[WAGE_STATE_SIZE]) +{ +#if defined(WAGE_64BIT) + const unsigned char *rc = wage_rc; + unsigned char round; + uint64_t x0, x1, x2, x3, x4; + uint32_t fb, temp; + + /* Load the state into 64-bit words. Each word will have up to eight + * 7-bit components with the MSB of each component fixed at zero. + * + * x0 = s[0] .. s[7] + * x1 = s[8] .. s[15] + * x2 = s[16] .. s[23] + * x3 = s[24] .. s[31] + * x4 = s[32] .. s[36] + */ + x0 = le_load_word64(s); + x1 = le_load_word64(s + 8); + x2 = le_load_word64(s + 16); + x3 = le_load_word64(s + 24); + x4 = le_load_word32(s + 32) | (((uint64_t)(s[36])) << 32); + + /* Perform all rounds 3 at a time to reduce the state rotation overhead */ + for (round = 0; round < (WAGE_NUM_ROUNDS / 3); ++round, rc += 6) { + /* Calculate the feedback value for the LFSR. + * + * fb = omega(s[0]) ^ s[6] ^ s[8] ^ s[12] ^ s[13] ^ s[19] ^ + * s[24] ^ s[26] ^ s[30] ^ s[31] ^ WGP(s[36]) ^ RC1[round] + * + * where omega(x) is (x >> 1) if the low bit of x is zero and + * (x >> 1) ^ 0x78 if the low bit of x is one. + */ + /* fb0 = omega(s[0]), fb1 = omega(s[1]), fb2 = omega(s[2]) */ + temp = (uint32_t)x0; + fb = (temp & 0x00010101U) << 6; + fb ^= (fb >> 1); + fb ^= (fb >> 2); + fb ^= (temp >> 1) & 0x003F3F3FU; + /* fb0 ^= s[6], fb1 ^= s[7], fb2 ^= s[8] */ + fb ^= (uint32_t)(x0 >> 48); + fb ^= ((uint32_t)x1) << 16; + /* fb0 ^= s[8], fb1 ^= s[9], fb2 ^= s[10] */ + fb ^= (uint32_t)x1; + /* fb0 ^= s[12], fb1 ^= s[13], fb2 ^= s[14] */ + fb ^= (uint32_t)(x1 >> 32); + /* fb0 ^= s[13], fb1 ^= s[14], fb2 ^= s[15] */ + fb ^= (uint32_t)(x1 >> 40); + /* fb0 ^= s[19], fb1 ^= s[20], fb2 ^= s[21] */ + fb ^= (uint32_t)(x2 >> 24); + /* fb0 ^= s[24], fb1 ^= s[25], fb2 ^= s[26] */ + fb ^= (uint32_t)x3; + /* fb0 ^= s[26], fb1 ^= s[27], fb2 ^= s[28] */ + fb ^= (uint32_t)(x3 >> 16); + /* fb0 ^= s[30], fb1 ^= s[31], fb2 ^= s[32] */ + fb ^= (uint32_t)(x3 >> 48); + fb ^= ((uint32_t)x4) << 16; + /* fb0 ^= s[31], fb1 ^= s[32], fb2 ^= s[33] */ + fb ^= (uint32_t)(x3 >> 56); + fb ^= ((uint32_t)x4) << 8; + /* fb0,1,2 ^= RC1 */ + temp = rc[1] | (((uint32_t)(rc[3])) << 8) | (((uint32_t)(rc[5])) << 16); + fb ^= temp; + /* fb0 ^= WGP(s[36]) */ + fb ^= wage_wgp[(uint8_t)(x4 >> 32)]; + /* fb1 ^= WGP(fb0) */ + fb ^= ((uint32_t)(wage_wgp[fb & 0xFF])) << 8; + /* fb2 ^= WGP(fb1) */ + fb ^= ((uint32_t)(wage_wgp[(fb >> 8) & 0xFF])) << 16; + + /* Apply the S-box and WGP permutation to certain components */ + /* s[5] ^= sbox[s[8]], s[6] ^= sbox[s[9]], s[7] ^= sbox[s[10]] */ + x0 ^= ((uint64_t)wage_sbox_parallel_3((uint32_t)x1)) << 40; + /* s[11] ^= sbox[s[15]], s[12] ^= sbox[s[16]], s[13] ^= sbox[s[17]] */ + x1 ^= ((uint64_t)wage_sbox_parallel_3 + ((uint32_t)((x1 >> 56) | (x2 << 8)))) << 24; + /* s[24] ^= sbox[s[27]], s[25] ^= sbox[s[28]], s[26] ^= sbox[s[29]] */ + x3 ^= (uint64_t)wage_sbox_parallel_3((uint32_t)(x3 >> 24)); + /* s[30] ^= sbox[s[34]], s[31] ^= sbox[s[35]], s[32] ^= sbox[s[36]] */ + temp = wage_sbox_parallel_3((uint32_t)(x4 >> 16)); + x3 ^= ((uint64_t)temp) << 48; + x4 ^= temp >> 16; + /* s[19] ^= WGP[s[18]] ^ RC0 */ + temp = (uint32_t)(x2 >> 16); /* s[18..21] */ + temp ^= ((uint32_t)(wage_wgp[temp & 0x7F])) << 8; + temp ^= ((uint32_t)(rc[0])) << 8; + /* s[20] ^= WGP[s[19]] ^ RC0 */ + temp ^= ((uint32_t)(wage_wgp[(temp >> 8) & 0x7F])) << 16; + temp ^= ((uint32_t)(rc[2])) << 16; + /* s[21] ^= WGP[s[20]] ^ RC0 */ + temp ^= ((uint32_t)(wage_wgp[(temp >> 16) & 0x7F])) << 24; + temp ^= ((uint32_t)(rc[4])) << 24; + temp &= 0x7F7F7F00U; + x2 = (x2 & 0xFFFF000000FFFFFFULL) | (((uint64_t)temp) << 16); + + /* Rotate the components of the state by 3 positions */ + x0 = (x0 >> 24) | (x1 << 40); + x1 = (x1 >> 24) | (x2 << 40); + x2 = (x2 >> 24) | (x3 << 40); + x3 = (x3 >> 24) | (x4 << 40); + x4 = (x4 >> 24) | (((uint64_t)(fb & 0x00FFFFFFU)) << 16); + } + + /* Save the words back to the state */ + le_store_word64(s, x0); + le_store_word64(s + 8, x1); + le_store_word64(s + 16, x2); + le_store_word64(s + 24, x3); + le_store_word32(s + 32, (uint32_t)x4); + s[36] = (unsigned char)(x4 >> 32); +#else /* 8-bit version of WAGE */ + const unsigned char *rc = wage_rc; + unsigned char round, index; + unsigned char fb0, fb1, fb2; + uint32_t temp; + + /* Perform all rounds 3 at a time to reduce the state rotation overhead */ + for (round = 0; round < (WAGE_NUM_ROUNDS / 3); ++round, rc += 6) { + /* Calculate the feedback value for the LFSR. + * + * fb = omega(s[0]) ^ s[6] ^ s[8] ^ s[12] ^ s[13] ^ s[19] ^ + * s[24] ^ s[26] ^ s[30] ^ s[31] ^ WGP(s[36]) ^ RC1[round] + * + * where omega(x) is (x >> 1) if the low bit of x is zero and + * (x >> 1) ^ 0x78 if the low bit of x is one. + */ + fb0 = (s[0] >> 1) ^ (0x78 & -(s[0] & 0x01)); + fb0 ^= s[6] ^ s[8] ^ s[12] ^ s[13] ^ s[19] ^ + s[24] ^ s[26] ^ s[30] ^ s[31] ^ rc[1]; + fb0 ^= wage_wgp[s[36]]; + fb1 = (s[1] >> 1) ^ (0x78 & -(s[1] & 0x01)); + fb1 ^= s[7] ^ s[9] ^ s[13] ^ s[14] ^ s[20] ^ + s[25] ^ s[27] ^ s[31] ^ s[32] ^ rc[3]; + fb1 ^= wage_wgp[fb0]; + fb2 = (s[2] >> 1) ^ (0x78 & -(s[2] & 0x01)); + fb2 ^= s[8] ^ s[10] ^ s[14] ^ s[15] ^ s[21] ^ + s[26] ^ s[28] ^ s[32] ^ s[33] ^ rc[5]; + fb2 ^= wage_wgp[fb1]; + + /* Apply the S-box and WGP permutation to certain components */ + temp = s[8] | (((uint32_t)(s[9])) << 8) | (((uint32_t)(s[10])) << 16); + temp = wage_sbox_parallel_3(temp); + s[5] ^= (unsigned char)temp; + s[6] ^= (unsigned char)(temp >> 8); + s[7] ^= (unsigned char)(temp >> 16); + temp = s[15] | (((uint32_t)(s[16])) << 8) | (((uint32_t)(s[17])) << 16); + temp = wage_sbox_parallel_3(temp); + s[11] ^= (unsigned char)temp; + s[12] ^= (unsigned char)(temp >> 8); + s[13] ^= (unsigned char)(temp >> 16); + s[19] ^= wage_wgp[s[18]] ^ rc[0]; + s[20] ^= wage_wgp[s[19]] ^ rc[2]; + s[21] ^= wage_wgp[s[20]] ^ rc[4]; + temp = s[27] | (((uint32_t)(s[28])) << 8) | (((uint32_t)(s[29])) << 16); + temp = wage_sbox_parallel_3(temp); + s[24] ^= (unsigned char)temp; + s[25] ^= (unsigned char)(temp >> 8); + s[26] ^= (unsigned char)(temp >> 16); + temp = s[34] | (((uint32_t)(s[35])) << 8) | (((uint32_t)(s[36])) << 16); + temp = wage_sbox_parallel_3(temp); + s[30] ^= (unsigned char)temp; + s[31] ^= (unsigned char)(temp >> 8); + s[32] ^= (unsigned char)(temp >> 16); + + /* Rotate the components of the state by 3 positions */ + for (index = 0; index < WAGE_STATE_SIZE - 3; ++index) + s[index] = s[index + 3]; + s[WAGE_STATE_SIZE - 3] = fb0; + s[WAGE_STATE_SIZE - 2] = fb1; + s[WAGE_STATE_SIZE - 1] = fb2; + } +#endif +} + +/* 7-bit components for the rate: 8, 9, 15, 16, 18, 27, 28, 34, 35, 36 */ + +void wage_absorb + (unsigned char s[WAGE_STATE_SIZE], const unsigned char data[8], + unsigned char domain) +{ + uint32_t temp; + temp = be_load_word32(data); + s[8] ^= (unsigned char)(temp >> 25); + s[9] ^= (unsigned char)((temp >> 18) & 0x7F); + s[15] ^= (unsigned char)((temp >> 11) & 0x7F); + s[16] ^= (unsigned char)((temp >> 4) & 0x7F); + s[18] ^= (unsigned char)((temp << 3) & 0x7F); + temp = be_load_word32(data + 4); + s[18] ^= (unsigned char)(temp >> 29); + s[27] ^= (unsigned char)((temp >> 22) & 0x7F); + s[28] ^= (unsigned char)((temp >> 15) & 0x7F); + s[34] ^= (unsigned char)((temp >> 8) & 0x7F); + s[35] ^= (unsigned char)((temp >> 1) & 0x7F); + s[36] ^= (unsigned char)((temp << 6) & 0x7F); + s[0] ^= domain; +} + +void wage_get_rate + (const unsigned char s[WAGE_STATE_SIZE], unsigned char data[8]) +{ + uint32_t temp; + temp = ((uint32_t)(s[8])) << 25; + temp |= ((uint32_t)(s[9])) << 18; + temp |= ((uint32_t)(s[15])) << 11; + temp |= ((uint32_t)(s[16])) << 4; + temp |= ((uint32_t)(s[18])) >> 3; + be_store_word32(data, temp); + temp = ((uint32_t)(s[18])) << 29; + temp |= ((uint32_t)(s[27])) << 22; + temp |= ((uint32_t)(s[28])) << 15; + temp |= ((uint32_t)(s[34])) << 8; + temp |= ((uint32_t)(s[35])) << 1; + temp |= ((uint32_t)(s[36])) >> 6; + be_store_word32(data + 4, temp); +} + +void wage_set_rate + (unsigned char s[WAGE_STATE_SIZE], const unsigned char data[8], + unsigned char domain) +{ + uint32_t temp; + temp = be_load_word32(data); + s[8] = (unsigned char)(temp >> 25); + s[9] = (unsigned char)((temp >> 18) & 0x7F); + s[15] = (unsigned char)((temp >> 11) & 0x7F); + s[16] = (unsigned char)((temp >> 4) & 0x7F); + s[18] = (unsigned char)((temp << 3) & 0x7F); + temp = be_load_word32(data + 4); + s[18] ^= (unsigned char)(temp >> 29); + s[27] = (unsigned char)((temp >> 22) & 0x7F); + s[28] = (unsigned char)((temp >> 15) & 0x7F); + s[34] = (unsigned char)((temp >> 8) & 0x7F); + s[35] = (unsigned char)((temp >> 1) & 0x7F); + s[36] = (unsigned char)(((temp << 6) & 0x40) ^ (s[36] & 0x3F)); + s[0] ^= domain; +} + +/** + * \brief Converts a 128-bit value into an array of 7-bit components. + * + * \param out Points to the output array of 7-bit components. + * \param in Points to the 128-bit value to convert. + */ +static void wage_128bit_to_components + (unsigned char out[19], const unsigned char *in) +{ + uint32_t temp; + temp = be_load_word32(in); + out[0] = (unsigned char)(temp >> 25); + out[1] = (unsigned char)((temp >> 18) & 0x7F); + out[2] = (unsigned char)((temp >> 11) & 0x7F); + out[3] = (unsigned char)((temp >> 4) & 0x7F); + out[4] = (unsigned char)((temp << 3) & 0x7F); + temp = be_load_word32(in + 4); + out[4] ^= (unsigned char)(temp >> 29); + out[5] = (unsigned char)((temp >> 22) & 0x7F); + out[6] = (unsigned char)((temp >> 15) & 0x7F); + out[7] = (unsigned char)((temp >> 8) & 0x7F); + out[8] = (unsigned char)((temp >> 1) & 0x7F); + out[18] = (unsigned char)((temp << 6) & 0x7F); + temp = be_load_word32(in + 8); + out[9] = (unsigned char)(temp >> 25); + out[10] = (unsigned char)((temp >> 18) & 0x7F); + out[11] = (unsigned char)((temp >> 11) & 0x7F); + out[12] = (unsigned char)((temp >> 4) & 0x7F); + out[13] = (unsigned char)((temp << 3) & 0x7F); + temp = be_load_word32(in + 12); + out[13] ^= (unsigned char)(temp >> 29); + out[14] = (unsigned char)((temp >> 22) & 0x7F); + out[15] = (unsigned char)((temp >> 15) & 0x7F); + out[16] = (unsigned char)((temp >> 8) & 0x7F); + out[17] = (unsigned char)((temp >> 1) & 0x7F); + out[18] ^= (unsigned char)((temp << 5) & 0x20); +} + +void wage_absorb_key + (unsigned char s[WAGE_STATE_SIZE], const unsigned char *key) +{ + unsigned char components[19]; + wage_128bit_to_components(components, key); + s[8] ^= components[0]; + s[9] ^= components[1]; + s[15] ^= components[2]; + s[16] ^= components[3]; + s[18] ^= components[4]; + s[27] ^= components[5]; + s[28] ^= components[6]; + s[34] ^= components[7]; + s[35] ^= components[8]; + s[36] ^= components[18] & 0x40; + wage_permute(s); + s[8] ^= components[9]; + s[9] ^= components[10]; + s[15] ^= components[11]; + s[16] ^= components[12]; + s[18] ^= components[13]; + s[27] ^= components[14]; + s[28] ^= components[15]; + s[34] ^= components[16]; + s[35] ^= components[17]; + s[36] ^= (components[18] << 1) & 0x40; + wage_permute(s); +} + +void wage_init + (unsigned char s[WAGE_STATE_SIZE], + const unsigned char *key, const unsigned char *nonce) +{ + unsigned char components[19]; + + /* Initialize the state with the key and nonce */ + wage_128bit_to_components(components, key); + s[0] = components[0]; + s[1] = components[2]; + s[2] = components[4]; + s[3] = components[6]; + s[4] = components[8]; + s[5] = components[10]; + s[6] = components[12]; + s[7] = components[14]; + s[8] = components[16]; + s[18] = components[18]; + s[19] = components[1]; + s[20] = components[3]; + s[21] = components[5]; + s[22] = components[7]; + s[23] = components[9]; + s[24] = components[11]; + s[25] = components[13]; + s[26] = components[15]; + s[27] = components[17]; + wage_128bit_to_components(components, nonce); + s[9] = components[1]; + s[10] = components[3]; + s[11] = components[5]; + s[12] = components[7]; + s[13] = components[9]; + s[14] = components[11]; + s[15] = components[13]; + s[16] = components[17]; + s[17] = components[15]; + s[18] ^= (components[18] >> 2); + s[28] = components[0]; + s[29] = components[2]; + s[30] = components[4]; + s[31] = components[6]; + s[32] = components[8]; + s[33] = components[10]; + s[34] = components[12]; + s[35] = components[14]; + s[36] = components[16]; + + /* Permute the state to absorb the key and nonce */ + wage_permute(s); + + /* Absorb the key again and permute the state */ + wage_absorb_key(s, key); +} + +void wage_extract_tag + (const unsigned char s[WAGE_STATE_SIZE], unsigned char tag[16]) +{ + unsigned char components[19]; + uint32_t temp; + + /* Extract the 7-bit components that make up the tag */ + for (temp = 0; temp < 9; ++temp) { + components[temp * 2] = s[28 + temp]; + components[temp * 2 + 1] = s[ 9 + temp]; + } + components[18] = (s[18] << 2) & 0x60; + + /* Convert from 7-bit component form back into bytes */ + temp = ((uint32_t)(components[0])) << 25; + temp |= ((uint32_t)(components[1])) << 18; + temp |= ((uint32_t)(components[2])) << 11; + temp |= ((uint32_t)(components[3])) << 4; + temp |= ((uint32_t)(components[4])) >> 3; + be_store_word32(tag, temp); + temp = ((uint32_t)(components[4])) << 29; + temp |= ((uint32_t)(components[5])) << 22; + temp |= ((uint32_t)(components[6])) << 15; + temp |= ((uint32_t)(components[7])) << 8; + temp |= ((uint32_t)(components[8])) << 1; + temp |= ((uint32_t)(components[9])) >> 6; + be_store_word32(tag + 4, temp); + temp = ((uint32_t)(components[9])) << 26; + temp |= ((uint32_t)(components[10])) << 19; + temp |= ((uint32_t)(components[11])) << 12; + temp |= ((uint32_t)(components[12])) << 5; + temp |= ((uint32_t)(components[13])) >> 2; + be_store_word32(tag + 8, temp); + temp = ((uint32_t)(components[13])) << 30; + temp |= ((uint32_t)(components[14])) << 23; + temp |= ((uint32_t)(components[15])) << 16; + temp |= ((uint32_t)(components[16])) << 9; + temp |= ((uint32_t)(components[17])) << 2; + temp |= ((uint32_t)(components[18])) >> 5; + be_store_word32(tag + 12, temp); +} diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.h b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.h new file mode 100644 index 0000000..a0d23d7 --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/internal-wage.h @@ -0,0 +1,117 @@ +/* + * 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_WAGE_H +#define LW_INTERNAL_WAGE_H + +#include "internal-util.h" + +/** + * \file internal-wage.h + * \brief Internal implementation of the WAGE permutation. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/wage + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the WAGE state in bytes. + * + * The state is 259 bits, divided into 37 7-bit components, one per byte. + */ +#define WAGE_STATE_SIZE 37 + +/** + * \brief Permutes the WAGE state. + * + * \param s The WAGE state to be permuted. + */ +void wage_permute(unsigned char s[WAGE_STATE_SIZE]); + +/** + * \brief Absorbs 8 bytes into the WAGE state. + * + * \param s The WAGE state to be permuted. + * \param data The data to be absorbed. + * \param domain The domain separator for the absorbed data. + */ +void wage_absorb + (unsigned char s[WAGE_STATE_SIZE], const unsigned char data[8], + unsigned char domain); + +/** + * \brief Gets the 8 bytes of the rate from the WAGE state. + * + * \param s The WAGE state to get the bytes from. + * \param data Points to the buffer to receive the extracted bytes. + */ +void wage_get_rate + (const unsigned char s[WAGE_STATE_SIZE], unsigned char data[8]); + +/** + * \brief Sets the 8 bytes of the rate in the WAGE state. + * + * \param s The WAGE state to set the rate in. + * \param data Points to the bytes to set into the rate. + * \param domain The domain separator for the rate data. + */ +void wage_set_rate + (unsigned char s[WAGE_STATE_SIZE], const unsigned char data[8], + unsigned char domain); + +/** + * \brief Absorbs 16 key bytes into the WAGE state. + * + * \param s The WAGE state to be permuted. + * \param key Points to the key data to be absorbed. + */ +void wage_absorb_key + (unsigned char s[WAGE_STATE_SIZE], const unsigned char *key); + +/** + * \brief Initializes the WAGE state with a key and nonce. + * + * \param s The WAGE state to be initialized. + * \param key Points to the 128-bit key. + * \param nonce Points to the 128-bit nonce. + */ +void wage_init + (unsigned char s[WAGE_STATE_SIZE], + const unsigned char *key, const unsigned char *nonce); + +/** + * \brief Extracts the 128-bit authentication tag from the WAGE state. + * + * \param s The WAGE state to extract the tag from. + * \param tag Points to the buffer to receive the extracted tag. + */ +void wage_extract_tag + (const unsigned char s[WAGE_STATE_SIZE], unsigned char tag[16]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.c b/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.c new file mode 100644 index 0000000..374409b --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.c @@ -0,0 +1,168 @@ +/* + * 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 "wage.h" +#include "internal-wage.h" +#include + +aead_cipher_t const wage_cipher = { + "WAGE", + WAGE_KEY_SIZE, + WAGE_NONCE_SIZE, + WAGE_TAG_SIZE, + AEAD_FLAG_NONE, + wage_aead_encrypt, + wage_aead_decrypt +}; + +/** + * \brief Rate of absorbing data into the WAGE state in sponge mode. + */ +#define WAGE_RATE 8 + +/** + * \brief Processes associated data for WAGE. + * + * \param state Points to the WAGE state. + * \param pad Points to an 8-byte temporary buffer for handling padding. + * \param ad Points to the associated data. + * \param adlen Length of the associated data. + */ +static void wage_process_ad + (unsigned char state[WAGE_STATE_SIZE], unsigned char pad[WAGE_RATE], + const unsigned char *ad, unsigned long long adlen) +{ + unsigned temp; + + /* Process as many full blocks as possible */ + while (adlen >= WAGE_RATE) { + wage_absorb(state, ad, 0x40); + wage_permute(state); + ad += WAGE_RATE; + adlen -= WAGE_RATE; + } + + /* Pad and absorb the final block */ + temp = (unsigned)adlen; + memcpy(pad, ad, temp); + pad[temp] = 0x80; + memset(pad + temp + 1, 0, WAGE_RATE - temp - 1); + wage_absorb(state, pad, 0x40); + wage_permute(state); +} + +int wage_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) +{ + unsigned char state[WAGE_STATE_SIZE]; + unsigned char block[WAGE_RATE]; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + WAGE_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + wage_init(state, k, npub); + if (adlen != 0) + wage_process_ad(state, block, ad, adlen); + + /* Encrypts the plaintext to produce the ciphertext */ + while (mlen >= WAGE_RATE) { + wage_get_rate(state, block); + lw_xor_block(block, m, WAGE_RATE); + wage_set_rate(state, block, 0x20); + wage_permute(state); + memcpy(c, block, WAGE_RATE); + c += WAGE_RATE; + m += WAGE_RATE; + mlen -= WAGE_RATE; + } + temp = (unsigned)mlen; + wage_get_rate(state, block); + lw_xor_block(block, m, temp); + block[temp] ^= 0x80; + wage_set_rate(state, block, 0x20); + wage_permute(state); + memcpy(c, block, temp); + + /* Generate and extract the authentication tag */ + wage_absorb_key(state, k); + wage_extract_tag(state, c + temp); + return 0; +} + +int wage_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) +{ + unsigned char state[WAGE_STATE_SIZE]; + unsigned char block[WAGE_TAG_SIZE]; + unsigned char *mtemp = m; + unsigned temp; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < WAGE_TAG_SIZE) + return -1; + *mlen = clen - WAGE_TAG_SIZE; + + /* Initialize the state and absorb the associated data */ + wage_init(state, k, npub); + if (adlen != 0) + wage_process_ad(state, block, ad, adlen); + + /* Decrypts the ciphertext to produce the plaintext */ + clen -= WAGE_TAG_SIZE; + while (clen >= WAGE_RATE) { + wage_get_rate(state, block); + lw_xor_block(block, c, WAGE_RATE); + wage_set_rate(state, c, 0x20); + wage_permute(state); + memcpy(m, block, WAGE_RATE); + c += WAGE_RATE; + m += WAGE_RATE; + clen -= WAGE_RATE; + } + temp = (unsigned)clen; + wage_get_rate(state, block); + lw_xor_block_2_src(block + 8, block, c, temp); + memcpy(block, c, temp); + block[temp] ^= 0x80; + wage_set_rate(state, block, 0x20); + wage_permute(state); + memcpy(m, block + 8, temp); + + /* Generate and check the authentication tag */ + wage_absorb_key(state, k); + wage_extract_tag(state, block); + return aead_check_tag(mtemp, *mlen, block, c + temp, WAGE_TAG_SIZE); +} diff --git a/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.h b/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.h new file mode 100644 index 0000000..2a620c4 --- /dev/null +++ b/wage/Implementations/crypto_aead/wageae128v1/rhys/wage.h @@ -0,0 +1,127 @@ +/* + * 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_WAGE_H +#define LWCRYPTO_WAGE_H + +#include "aead-common.h" + +/** + * \file wage.h + * \brief WAGE authenticated encryption algorithm. + * + * WAGE is an authenticated encryption algorithm that is built around the + * 259-bit WAGE permutation. The algorithm has a 128-bit key, a 128-bit + * nonce, and a 128-bit authentication tag. It is an evolution of the + * WG series of stream ciphers. + * + * References: https://uwaterloo.ca/communications-security-lab/lwc/wage + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for WAGE. + */ +#define WAGE_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for WAGE. + */ +#define WAGE_TAG_SIZE 16 + +/** + * \brief Size of the nonce for WAGE. + */ +#define WAGE_NONCE_SIZE 16 + +/** + * \brief Meta-information block for the WAGE cipher. + */ +extern aead_cipher_t const wage_cipher; + +/** + * \brief Encrypts and authenticates a packet with WAGE. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa wage_aead_decrypt() + */ +int wage_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); + +/** + * \brief Decrypts and authenticates a packet with WAGE. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa wage_aead_encrypt() + */ +int wage_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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.c b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.c new file mode 100644 index 0000000..84fc53a --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.c @@ -0,0 +1,69 @@ +/* + * 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; +} diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.h b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.h new file mode 100644 index 0000000..2be95eb --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/aead-common.h @@ -0,0 +1,256 @@ +/* + * 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 + +/** + * \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 diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/api.h b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/api.h new file mode 100644 index 0000000..b2f8a36 --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/encrypt.c b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/encrypt.c new file mode 100644 index 0000000..f7bb1b4 --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/encrypt.c @@ -0,0 +1,26 @@ + +#include "xoodyak.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 xoodyak_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 xoodyak_aead_decrypt + (m, mlen, nsec, c, clen, ad, adlen, npub, k); +} diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-util.h b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-util.h new file mode 100644 index 0000000..e79158c --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-util.h @@ -0,0 +1,557 @@ +/* + * 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_UTIL_H +#define LW_INTERNAL_UTIL_H + +#include + +/* Figure out how to inline functions using this C compiler */ +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L +#define STATIC_INLINE static inline +#elif defined(__GNUC__) || defined(__clang__) +#define STATIC_INLINE static __inline__ +#else +#define STATIC_INLINE static +#endif + +/* Try to figure out whether the CPU is little-endian or big-endian. + * May need to modify this to include new compiler-specific defines. + * Alternatively, define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ in your + * compiler flags when you compile this library */ +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__i386) || defined(__i386__) || \ + defined(__AVR__) || defined(__arm) || defined(__arm__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) || \ + defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM_FP) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 1234) || \ + defined(__LITTLE_ENDIAN__) +#define LW_UTIL_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == 4321) || \ + defined(__BIG_ENDIAN__) +/* Big endian */ +#else +#error "Cannot determine the endianess of this platform" +#endif + +/* Helper macros to load and store values while converting endian-ness */ + +/* Load a big-endian 32-bit word from a byte buffer */ +#define be_load_word32(ptr) \ + ((((uint32_t)((ptr)[0])) << 24) | \ + (((uint32_t)((ptr)[1])) << 16) | \ + (((uint32_t)((ptr)[2])) << 8) | \ + ((uint32_t)((ptr)[3]))) + +/* Store a big-endian 32-bit word into a byte buffer */ +#define be_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 24); \ + (ptr)[1] = (uint8_t)(_x >> 16); \ + (ptr)[2] = (uint8_t)(_x >> 8); \ + (ptr)[3] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 32-bit word from a byte buffer */ +#define le_load_word32(ptr) \ + ((((uint32_t)((ptr)[3])) << 24) | \ + (((uint32_t)((ptr)[2])) << 16) | \ + (((uint32_t)((ptr)[1])) << 8) | \ + ((uint32_t)((ptr)[0]))) + +/* Store a little-endian 32-bit word into a byte buffer */ +#define le_store_word32(ptr, x) \ + do { \ + uint32_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + } while (0) + +/* Load a big-endian 64-bit word from a byte buffer */ +#define be_load_word64(ptr) \ + ((((uint64_t)((ptr)[0])) << 56) | \ + (((uint64_t)((ptr)[1])) << 48) | \ + (((uint64_t)((ptr)[2])) << 40) | \ + (((uint64_t)((ptr)[3])) << 32) | \ + (((uint64_t)((ptr)[4])) << 24) | \ + (((uint64_t)((ptr)[5])) << 16) | \ + (((uint64_t)((ptr)[6])) << 8) | \ + ((uint64_t)((ptr)[7]))) + +/* Store a big-endian 64-bit word into a byte buffer */ +#define be_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 56); \ + (ptr)[1] = (uint8_t)(_x >> 48); \ + (ptr)[2] = (uint8_t)(_x >> 40); \ + (ptr)[3] = (uint8_t)(_x >> 32); \ + (ptr)[4] = (uint8_t)(_x >> 24); \ + (ptr)[5] = (uint8_t)(_x >> 16); \ + (ptr)[6] = (uint8_t)(_x >> 8); \ + (ptr)[7] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 64-bit word from a byte buffer */ +#define le_load_word64(ptr) \ + ((((uint64_t)((ptr)[7])) << 56) | \ + (((uint64_t)((ptr)[6])) << 48) | \ + (((uint64_t)((ptr)[5])) << 40) | \ + (((uint64_t)((ptr)[4])) << 32) | \ + (((uint64_t)((ptr)[3])) << 24) | \ + (((uint64_t)((ptr)[2])) << 16) | \ + (((uint64_t)((ptr)[1])) << 8) | \ + ((uint64_t)((ptr)[0]))) + +/* Store a little-endian 64-bit word into a byte buffer */ +#define le_store_word64(ptr, x) \ + do { \ + uint64_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + (ptr)[2] = (uint8_t)(_x >> 16); \ + (ptr)[3] = (uint8_t)(_x >> 24); \ + (ptr)[4] = (uint8_t)(_x >> 32); \ + (ptr)[5] = (uint8_t)(_x >> 40); \ + (ptr)[6] = (uint8_t)(_x >> 48); \ + (ptr)[7] = (uint8_t)(_x >> 56); \ + } while (0) + +/* Load a big-endian 16-bit word from a byte buffer */ +#define be_load_word16(ptr) \ + ((((uint16_t)((ptr)[0])) << 8) | \ + ((uint16_t)((ptr)[1]))) + +/* Store a big-endian 16-bit word into a byte buffer */ +#define be_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)(_x >> 8); \ + (ptr)[1] = (uint8_t)_x; \ + } while (0) + +/* Load a little-endian 16-bit word from a byte buffer */ +#define le_load_word16(ptr) \ + ((((uint16_t)((ptr)[1])) << 8) | \ + ((uint16_t)((ptr)[0]))) + +/* Store a little-endian 16-bit word into a byte buffer */ +#define le_store_word16(ptr, x) \ + do { \ + uint16_t _x = (x); \ + (ptr)[0] = (uint8_t)_x; \ + (ptr)[1] = (uint8_t)(_x >> 8); \ + } while (0) + +/* XOR a source byte buffer against a destination */ +#define lw_xor_block(dest, src, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ ^= *_src++; \ + --_len; \ + } \ + } while (0) + +/* XOR two source byte buffers and put the result in a destination buffer */ +#define lw_xor_block_2_src(dest, src1, src2, len) \ + do { \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest++ = *_src1++ ^ *_src2++; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time */ +#define lw_xor_block_2_dest(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + *_dest2++ = (*_dest++ ^= *_src++); \ + --_len; \ + } \ + } while (0) + +/* XOR two byte buffers and write to a destination which at the same + * time copying the contents of src2 to dest2 */ +#define lw_xor_block_copy_src(dest2, dest, src1, src2, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src1 = (src1); \ + const unsigned char *_src2 = (src2); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src2++; \ + *_dest2++ = _temp; \ + *_dest++ = *_src1++ ^ _temp; \ + --_len; \ + } \ + } while (0) + +/* XOR a source byte buffer against a destination and write to another + * destination at the same time. This version swaps the source value + * into the "dest" buffer */ +#define lw_xor_block_swap(dest2, dest, src, len) \ + do { \ + unsigned char *_dest2 = (dest2); \ + unsigned char *_dest = (dest); \ + const unsigned char *_src = (src); \ + unsigned _len = (len); \ + while (_len > 0) { \ + unsigned char _temp = *_src++; \ + *_dest2++ = *_dest ^ _temp; \ + *_dest++ = _temp; \ + --_len; \ + } \ + } while (0) + +/* Rotation macros for 32-bit arguments */ + +/* Generic left rotate */ +#define leftRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (32 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate(a, bits) \ + (__extension__ ({ \ + uint32_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (32 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1(a) (leftRotate((a), 1)) +#define leftRotate2(a) (leftRotate((a), 2)) +#define leftRotate3(a) (leftRotate((a), 3)) +#define leftRotate4(a) (leftRotate((a), 4)) +#define leftRotate5(a) (leftRotate((a), 5)) +#define leftRotate6(a) (leftRotate((a), 6)) +#define leftRotate7(a) (leftRotate((a), 7)) +#define leftRotate8(a) (leftRotate((a), 8)) +#define leftRotate9(a) (leftRotate((a), 9)) +#define leftRotate10(a) (leftRotate((a), 10)) +#define leftRotate11(a) (leftRotate((a), 11)) +#define leftRotate12(a) (leftRotate((a), 12)) +#define leftRotate13(a) (leftRotate((a), 13)) +#define leftRotate14(a) (leftRotate((a), 14)) +#define leftRotate15(a) (leftRotate((a), 15)) +#define leftRotate16(a) (leftRotate((a), 16)) +#define leftRotate17(a) (leftRotate((a), 17)) +#define leftRotate18(a) (leftRotate((a), 18)) +#define leftRotate19(a) (leftRotate((a), 19)) +#define leftRotate20(a) (leftRotate((a), 20)) +#define leftRotate21(a) (leftRotate((a), 21)) +#define leftRotate22(a) (leftRotate((a), 22)) +#define leftRotate23(a) (leftRotate((a), 23)) +#define leftRotate24(a) (leftRotate((a), 24)) +#define leftRotate25(a) (leftRotate((a), 25)) +#define leftRotate26(a) (leftRotate((a), 26)) +#define leftRotate27(a) (leftRotate((a), 27)) +#define leftRotate28(a) (leftRotate((a), 28)) +#define leftRotate29(a) (leftRotate((a), 29)) +#define leftRotate30(a) (leftRotate((a), 30)) +#define leftRotate31(a) (leftRotate((a), 31)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1(a) (rightRotate((a), 1)) +#define rightRotate2(a) (rightRotate((a), 2)) +#define rightRotate3(a) (rightRotate((a), 3)) +#define rightRotate4(a) (rightRotate((a), 4)) +#define rightRotate5(a) (rightRotate((a), 5)) +#define rightRotate6(a) (rightRotate((a), 6)) +#define rightRotate7(a) (rightRotate((a), 7)) +#define rightRotate8(a) (rightRotate((a), 8)) +#define rightRotate9(a) (rightRotate((a), 9)) +#define rightRotate10(a) (rightRotate((a), 10)) +#define rightRotate11(a) (rightRotate((a), 11)) +#define rightRotate12(a) (rightRotate((a), 12)) +#define rightRotate13(a) (rightRotate((a), 13)) +#define rightRotate14(a) (rightRotate((a), 14)) +#define rightRotate15(a) (rightRotate((a), 15)) +#define rightRotate16(a) (rightRotate((a), 16)) +#define rightRotate17(a) (rightRotate((a), 17)) +#define rightRotate18(a) (rightRotate((a), 18)) +#define rightRotate19(a) (rightRotate((a), 19)) +#define rightRotate20(a) (rightRotate((a), 20)) +#define rightRotate21(a) (rightRotate((a), 21)) +#define rightRotate22(a) (rightRotate((a), 22)) +#define rightRotate23(a) (rightRotate((a), 23)) +#define rightRotate24(a) (rightRotate((a), 24)) +#define rightRotate25(a) (rightRotate((a), 25)) +#define rightRotate26(a) (rightRotate((a), 26)) +#define rightRotate27(a) (rightRotate((a), 27)) +#define rightRotate28(a) (rightRotate((a), 28)) +#define rightRotate29(a) (rightRotate((a), 29)) +#define rightRotate30(a) (rightRotate((a), 30)) +#define rightRotate31(a) (rightRotate((a), 31)) + +/* Rotation macros for 64-bit arguments */ + +/* Generic left rotate */ +#define leftRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (64 - (bits))); \ + })) + +/* Generic right rotate */ +#define rightRotate_64(a, bits) \ + (__extension__ ({ \ + uint64_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (64 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_64(a) (leftRotate_64((a), 1)) +#define leftRotate2_64(a) (leftRotate_64((a), 2)) +#define leftRotate3_64(a) (leftRotate_64((a), 3)) +#define leftRotate4_64(a) (leftRotate_64((a), 4)) +#define leftRotate5_64(a) (leftRotate_64((a), 5)) +#define leftRotate6_64(a) (leftRotate_64((a), 6)) +#define leftRotate7_64(a) (leftRotate_64((a), 7)) +#define leftRotate8_64(a) (leftRotate_64((a), 8)) +#define leftRotate9_64(a) (leftRotate_64((a), 9)) +#define leftRotate10_64(a) (leftRotate_64((a), 10)) +#define leftRotate11_64(a) (leftRotate_64((a), 11)) +#define leftRotate12_64(a) (leftRotate_64((a), 12)) +#define leftRotate13_64(a) (leftRotate_64((a), 13)) +#define leftRotate14_64(a) (leftRotate_64((a), 14)) +#define leftRotate15_64(a) (leftRotate_64((a), 15)) +#define leftRotate16_64(a) (leftRotate_64((a), 16)) +#define leftRotate17_64(a) (leftRotate_64((a), 17)) +#define leftRotate18_64(a) (leftRotate_64((a), 18)) +#define leftRotate19_64(a) (leftRotate_64((a), 19)) +#define leftRotate20_64(a) (leftRotate_64((a), 20)) +#define leftRotate21_64(a) (leftRotate_64((a), 21)) +#define leftRotate22_64(a) (leftRotate_64((a), 22)) +#define leftRotate23_64(a) (leftRotate_64((a), 23)) +#define leftRotate24_64(a) (leftRotate_64((a), 24)) +#define leftRotate25_64(a) (leftRotate_64((a), 25)) +#define leftRotate26_64(a) (leftRotate_64((a), 26)) +#define leftRotate27_64(a) (leftRotate_64((a), 27)) +#define leftRotate28_64(a) (leftRotate_64((a), 28)) +#define leftRotate29_64(a) (leftRotate_64((a), 29)) +#define leftRotate30_64(a) (leftRotate_64((a), 30)) +#define leftRotate31_64(a) (leftRotate_64((a), 31)) +#define leftRotate32_64(a) (leftRotate_64((a), 32)) +#define leftRotate33_64(a) (leftRotate_64((a), 33)) +#define leftRotate34_64(a) (leftRotate_64((a), 34)) +#define leftRotate35_64(a) (leftRotate_64((a), 35)) +#define leftRotate36_64(a) (leftRotate_64((a), 36)) +#define leftRotate37_64(a) (leftRotate_64((a), 37)) +#define leftRotate38_64(a) (leftRotate_64((a), 38)) +#define leftRotate39_64(a) (leftRotate_64((a), 39)) +#define leftRotate40_64(a) (leftRotate_64((a), 40)) +#define leftRotate41_64(a) (leftRotate_64((a), 41)) +#define leftRotate42_64(a) (leftRotate_64((a), 42)) +#define leftRotate43_64(a) (leftRotate_64((a), 43)) +#define leftRotate44_64(a) (leftRotate_64((a), 44)) +#define leftRotate45_64(a) (leftRotate_64((a), 45)) +#define leftRotate46_64(a) (leftRotate_64((a), 46)) +#define leftRotate47_64(a) (leftRotate_64((a), 47)) +#define leftRotate48_64(a) (leftRotate_64((a), 48)) +#define leftRotate49_64(a) (leftRotate_64((a), 49)) +#define leftRotate50_64(a) (leftRotate_64((a), 50)) +#define leftRotate51_64(a) (leftRotate_64((a), 51)) +#define leftRotate52_64(a) (leftRotate_64((a), 52)) +#define leftRotate53_64(a) (leftRotate_64((a), 53)) +#define leftRotate54_64(a) (leftRotate_64((a), 54)) +#define leftRotate55_64(a) (leftRotate_64((a), 55)) +#define leftRotate56_64(a) (leftRotate_64((a), 56)) +#define leftRotate57_64(a) (leftRotate_64((a), 57)) +#define leftRotate58_64(a) (leftRotate_64((a), 58)) +#define leftRotate59_64(a) (leftRotate_64((a), 59)) +#define leftRotate60_64(a) (leftRotate_64((a), 60)) +#define leftRotate61_64(a) (leftRotate_64((a), 61)) +#define leftRotate62_64(a) (leftRotate_64((a), 62)) +#define leftRotate63_64(a) (leftRotate_64((a), 63)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_64(a) (rightRotate_64((a), 1)) +#define rightRotate2_64(a) (rightRotate_64((a), 2)) +#define rightRotate3_64(a) (rightRotate_64((a), 3)) +#define rightRotate4_64(a) (rightRotate_64((a), 4)) +#define rightRotate5_64(a) (rightRotate_64((a), 5)) +#define rightRotate6_64(a) (rightRotate_64((a), 6)) +#define rightRotate7_64(a) (rightRotate_64((a), 7)) +#define rightRotate8_64(a) (rightRotate_64((a), 8)) +#define rightRotate9_64(a) (rightRotate_64((a), 9)) +#define rightRotate10_64(a) (rightRotate_64((a), 10)) +#define rightRotate11_64(a) (rightRotate_64((a), 11)) +#define rightRotate12_64(a) (rightRotate_64((a), 12)) +#define rightRotate13_64(a) (rightRotate_64((a), 13)) +#define rightRotate14_64(a) (rightRotate_64((a), 14)) +#define rightRotate15_64(a) (rightRotate_64((a), 15)) +#define rightRotate16_64(a) (rightRotate_64((a), 16)) +#define rightRotate17_64(a) (rightRotate_64((a), 17)) +#define rightRotate18_64(a) (rightRotate_64((a), 18)) +#define rightRotate19_64(a) (rightRotate_64((a), 19)) +#define rightRotate20_64(a) (rightRotate_64((a), 20)) +#define rightRotate21_64(a) (rightRotate_64((a), 21)) +#define rightRotate22_64(a) (rightRotate_64((a), 22)) +#define rightRotate23_64(a) (rightRotate_64((a), 23)) +#define rightRotate24_64(a) (rightRotate_64((a), 24)) +#define rightRotate25_64(a) (rightRotate_64((a), 25)) +#define rightRotate26_64(a) (rightRotate_64((a), 26)) +#define rightRotate27_64(a) (rightRotate_64((a), 27)) +#define rightRotate28_64(a) (rightRotate_64((a), 28)) +#define rightRotate29_64(a) (rightRotate_64((a), 29)) +#define rightRotate30_64(a) (rightRotate_64((a), 30)) +#define rightRotate31_64(a) (rightRotate_64((a), 31)) +#define rightRotate32_64(a) (rightRotate_64((a), 32)) +#define rightRotate33_64(a) (rightRotate_64((a), 33)) +#define rightRotate34_64(a) (rightRotate_64((a), 34)) +#define rightRotate35_64(a) (rightRotate_64((a), 35)) +#define rightRotate36_64(a) (rightRotate_64((a), 36)) +#define rightRotate37_64(a) (rightRotate_64((a), 37)) +#define rightRotate38_64(a) (rightRotate_64((a), 38)) +#define rightRotate39_64(a) (rightRotate_64((a), 39)) +#define rightRotate40_64(a) (rightRotate_64((a), 40)) +#define rightRotate41_64(a) (rightRotate_64((a), 41)) +#define rightRotate42_64(a) (rightRotate_64((a), 42)) +#define rightRotate43_64(a) (rightRotate_64((a), 43)) +#define rightRotate44_64(a) (rightRotate_64((a), 44)) +#define rightRotate45_64(a) (rightRotate_64((a), 45)) +#define rightRotate46_64(a) (rightRotate_64((a), 46)) +#define rightRotate47_64(a) (rightRotate_64((a), 47)) +#define rightRotate48_64(a) (rightRotate_64((a), 48)) +#define rightRotate49_64(a) (rightRotate_64((a), 49)) +#define rightRotate50_64(a) (rightRotate_64((a), 50)) +#define rightRotate51_64(a) (rightRotate_64((a), 51)) +#define rightRotate52_64(a) (rightRotate_64((a), 52)) +#define rightRotate53_64(a) (rightRotate_64((a), 53)) +#define rightRotate54_64(a) (rightRotate_64((a), 54)) +#define rightRotate55_64(a) (rightRotate_64((a), 55)) +#define rightRotate56_64(a) (rightRotate_64((a), 56)) +#define rightRotate57_64(a) (rightRotate_64((a), 57)) +#define rightRotate58_64(a) (rightRotate_64((a), 58)) +#define rightRotate59_64(a) (rightRotate_64((a), 59)) +#define rightRotate60_64(a) (rightRotate_64((a), 60)) +#define rightRotate61_64(a) (rightRotate_64((a), 61)) +#define rightRotate62_64(a) (rightRotate_64((a), 62)) +#define rightRotate63_64(a) (rightRotate_64((a), 63)) + +/* Rotate a 16-bit value left by a number of bits */ +#define leftRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (16 - (bits))); \ + })) + +/* Rotate a 16-bit value right by a number of bits */ +#define rightRotate_16(a, bits) \ + (__extension__ ({ \ + uint16_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (16 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_16(a) (leftRotate_16((a), 1)) +#define leftRotate2_16(a) (leftRotate_16((a), 2)) +#define leftRotate3_16(a) (leftRotate_16((a), 3)) +#define leftRotate4_16(a) (leftRotate_16((a), 4)) +#define leftRotate5_16(a) (leftRotate_16((a), 5)) +#define leftRotate6_16(a) (leftRotate_16((a), 6)) +#define leftRotate7_16(a) (leftRotate_16((a), 7)) +#define leftRotate8_16(a) (leftRotate_16((a), 8)) +#define leftRotate9_16(a) (leftRotate_16((a), 9)) +#define leftRotate10_16(a) (leftRotate_16((a), 10)) +#define leftRotate11_16(a) (leftRotate_16((a), 11)) +#define leftRotate12_16(a) (leftRotate_16((a), 12)) +#define leftRotate13_16(a) (leftRotate_16((a), 13)) +#define leftRotate14_16(a) (leftRotate_16((a), 14)) +#define leftRotate15_16(a) (leftRotate_16((a), 15)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_16(a) (rightRotate_16((a), 1)) +#define rightRotate2_16(a) (rightRotate_16((a), 2)) +#define rightRotate3_16(a) (rightRotate_16((a), 3)) +#define rightRotate4_16(a) (rightRotate_16((a), 4)) +#define rightRotate5_16(a) (rightRotate_16((a), 5)) +#define rightRotate6_16(a) (rightRotate_16((a), 6)) +#define rightRotate7_16(a) (rightRotate_16((a), 7)) +#define rightRotate8_16(a) (rightRotate_16((a), 8)) +#define rightRotate9_16(a) (rightRotate_16((a), 9)) +#define rightRotate10_16(a) (rightRotate_16((a), 10)) +#define rightRotate11_16(a) (rightRotate_16((a), 11)) +#define rightRotate12_16(a) (rightRotate_16((a), 12)) +#define rightRotate13_16(a) (rightRotate_16((a), 13)) +#define rightRotate14_16(a) (rightRotate_16((a), 14)) +#define rightRotate15_16(a) (rightRotate_16((a), 15)) + +/* Rotate an 8-bit value left by a number of bits */ +#define leftRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp << (bits)) | (_temp >> (8 - (bits))); \ + })) + +/* Rotate an 8-bit value right by a number of bits */ +#define rightRotate_8(a, bits) \ + (__extension__ ({ \ + uint8_t _temp = (a); \ + (_temp >> (bits)) | (_temp << (8 - (bits))); \ + })) + +/* Left rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define leftRotate1_8(a) (leftRotate_8((a), 1)) +#define leftRotate2_8(a) (leftRotate_8((a), 2)) +#define leftRotate3_8(a) (leftRotate_8((a), 3)) +#define leftRotate4_8(a) (leftRotate_8((a), 4)) +#define leftRotate5_8(a) (leftRotate_8((a), 5)) +#define leftRotate6_8(a) (leftRotate_8((a), 6)) +#define leftRotate7_8(a) (leftRotate_8((a), 7)) + +/* Right rotate by a specific number of bits. These macros may be replaced + * with more efficient ones on platforms that lack a barrel shifter */ +#define rightRotate1_8(a) (rightRotate_8((a), 1)) +#define rightRotate2_8(a) (rightRotate_8((a), 2)) +#define rightRotate3_8(a) (rightRotate_8((a), 3)) +#define rightRotate4_8(a) (rightRotate_8((a), 4)) +#define rightRotate5_8(a) (rightRotate_8((a), 5)) +#define rightRotate6_8(a) (rightRotate_8((a), 6)) +#define rightRotate7_8(a) (rightRotate_8((a), 7)) + +#endif diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.c b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.c new file mode 100644 index 0000000..f129833 --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.c @@ -0,0 +1,162 @@ +/* + * 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 "internal-xoodoo.h" + +void xoodoo_permute(xoodoo_state_t *state) +{ + static uint16_t const rc[XOODOO_ROUNDS] = { + 0x0058, 0x0038, 0x03C0, 0x00D0, 0x0120, 0x0014, + 0x0060, 0x002C, 0x0380, 0x00F0, 0x01A0, 0x0012 + }; + uint8_t round; + uint32_t x00, x01, x02, x03; + uint32_t x10, x11, x12, x13; + uint32_t x20, x21, x22, x23; + uint32_t t1, t2; + + /* Load the state and convert from little-endian byte order */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + x00 = state->S[0][0]; + x01 = state->S[0][1]; + x02 = state->S[0][2]; + x03 = state->S[0][3]; + x10 = state->S[1][0]; + x11 = state->S[1][1]; + x12 = state->S[1][2]; + x13 = state->S[1][3]; + x20 = state->S[2][0]; + x21 = state->S[2][1]; + x22 = state->S[2][2]; + x23 = state->S[2][3]; +#else + x00 = le_load_word32(state->B); + x01 = le_load_word32(state->B + 4); + x02 = le_load_word32(state->B + 8); + x03 = le_load_word32(state->B + 12); + x10 = le_load_word32(state->B + 16); + x11 = le_load_word32(state->B + 20); + x12 = le_load_word32(state->B + 24); + x13 = le_load_word32(state->B + 28); + x20 = le_load_word32(state->B + 32); + x21 = le_load_word32(state->B + 36); + x22 = le_load_word32(state->B + 40); + x23 = le_load_word32(state->B + 44); +#endif + + /* Perform all permutation rounds */ + for (round = 0; round < XOODOO_ROUNDS; ++round) { + /* Optimization ideas from the Xoodoo implementation here: + * https://github.com/XKCP/XKCP/tree/master/lib/low/Xoodoo/Optimized */ + + /* Step theta: Mix column parity */ + t1 = x03 ^ x13 ^ x23; + t2 = x00 ^ x10 ^ x20; + t1 = leftRotate5(t1) ^ leftRotate14(t1); + t2 = leftRotate5(t2) ^ leftRotate14(t2); + x00 ^= t1; + x10 ^= t1; + x20 ^= t1; + t1 = x01 ^ x11 ^ x21; + t1 = leftRotate5(t1) ^ leftRotate14(t1); + x01 ^= t2; + x11 ^= t2; + x21 ^= t2; + t2 = x02 ^ x12 ^ x22; + t2 = leftRotate5(t2) ^ leftRotate14(t2); + x02 ^= t1; + x12 ^= t1; + x22 ^= t1; + x03 ^= t2; + x13 ^= t2; + x23 ^= t2; + + /* Step rho-west: Plane shift */ + t1 = x13; + x13 = x12; + x12 = x11; + x11 = x10; + x10 = t1; + x20 = leftRotate11(x20); + x21 = leftRotate11(x21); + x22 = leftRotate11(x22); + x23 = leftRotate11(x23); + + /* Step iota: Add the round constant to the state */ + x00 ^= rc[round]; + + /* Step chi: Non-linear layer */ + x00 ^= (~x10) & x20; + x10 ^= (~x20) & x00; + x20 ^= (~x00) & x10; + x01 ^= (~x11) & x21; + x11 ^= (~x21) & x01; + x21 ^= (~x01) & x11; + x02 ^= (~x12) & x22; + x12 ^= (~x22) & x02; + x22 ^= (~x02) & x12; + x03 ^= (~x13) & x23; + x13 ^= (~x23) & x03; + x23 ^= (~x03) & x13; + + /* Step rho-east: Plane shift */ + x10 = leftRotate1(x10); + x11 = leftRotate1(x11); + x12 = leftRotate1(x12); + x13 = leftRotate1(x13); + t1 = leftRotate8(x22); + t2 = leftRotate8(x23); + x22 = leftRotate8(x20); + x23 = leftRotate8(x21); + x20 = t1; + x21 = t2; + } + + /* Convert back into little-endian and store to the output state */ +#if defined(LW_UTIL_LITTLE_ENDIAN) + state->S[0][0] = x00; + state->S[0][1] = x01; + state->S[0][2] = x02; + state->S[0][3] = x03; + state->S[1][0] = x10; + state->S[1][1] = x11; + state->S[1][2] = x12; + state->S[1][3] = x13; + state->S[2][0] = x20; + state->S[2][1] = x21; + state->S[2][2] = x22; + state->S[2][3] = x23; +#else + le_store_word32(state->B, x00); + le_store_word32(state->B + 4, x01); + le_store_word32(state->B + 8, x02); + le_store_word32(state->B + 12, x03); + le_store_word32(state->B + 16, x10); + le_store_word32(state->B + 20, x11); + le_store_word32(state->B + 24, x12); + le_store_word32(state->B + 28, x13); + le_store_word32(state->B + 32, x20); + le_store_word32(state->B + 36, x21); + le_store_word32(state->B + 40, x22); + le_store_word32(state->B + 44, x23); +#endif +} diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.h b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.h new file mode 100644 index 0000000..f6eddd8 --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/internal-xoodoo.h @@ -0,0 +1,80 @@ +/* + * 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_XOODOO_H +#define LW_INTERNAL_XOODOO_H + +#include "internal-util.h" + +/** + * \file internal-xoodoo.h + * \brief Internal implementation of the Xoodoo permutation. + * + * References: https://keccak.team/xoodyak.html + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Number of rows in the Xoodoo state. + */ +#define XOODOO_ROWS 3 + +/** + * \brief Number of columns in the Xoodoo state. + */ +#define XOODOO_COLS 4 + +/** + * \brief Number of rounds for the Xoodoo permutation. + */ +#define XOODOO_ROUNDS 12 + +/** + * \brief State information for the Xoodoo permutation. + */ +typedef union +{ + /** Words of the state */ + uint32_t S[XOODOO_ROWS][XOODOO_COLS]; + + /** Bytes of the state */ + uint8_t B[XOODOO_ROWS * XOODOO_COLS * sizeof(uint32_t)]; + +} xoodoo_state_t; + +/** + * \brief Permutes the Xoodoo state. + * + * \param state The Xoodoo state. + * + * The state will be in little-endian before and after the operation. + */ +void xoodoo_permute(xoodoo_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.c b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.c new file mode 100644 index 0000000..4ad4fce --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.c @@ -0,0 +1,321 @@ +/* + * 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 "xoodyak.h" +#include "internal-xoodoo.h" +#include + +aead_cipher_t const xoodyak_cipher = { + "Xoodyak", + XOODYAK_KEY_SIZE, + XOODYAK_NONCE_SIZE, + XOODYAK_TAG_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + xoodyak_aead_encrypt, + xoodyak_aead_decrypt +}; + +aead_hash_algorithm_t const xoodyak_hash_algorithm = { + "Xoodyak-Hash", + sizeof(xoodyak_hash_state_t), + XOODYAK_HASH_SIZE, + AEAD_FLAG_LITTLE_ENDIAN, + xoodyak_hash, + (aead_hash_init_t)xoodyak_hash_init, + (aead_hash_update_t)xoodyak_hash_absorb, + (aead_hash_finalize_t)xoodyak_hash_finalize, + (aead_xof_absorb_t)xoodyak_hash_absorb, + (aead_xof_squeeze_t)xoodyak_hash_squeeze +}; + +/** + * \brief Rate for absorbing data into the sponge state. + */ +#define XOODYAK_ABSORB_RATE 44 + +/** + * \brief Rate for squeezing data out of the sponge. + */ +#define XOODYAK_SQUEEZE_RATE 24 + +/** + * \brief Rate for absorbing and squeezing in hashing mode. + */ +#define XOODYAK_HASH_RATE 16 + +/** + * \brief Phase identifier for "up" mode, which indicates that a block + * permutation has just been performed. + */ +#define XOODYAK_PHASE_UP 0 + +/** + * \brief Phase identifier for "down" mode, which indicates that data has + * been absorbed but that a block permutation has not been done yet. + */ +#define XOODYAK_PHASE_DOWN 1 + +/** + * \brief Absorbs data into the Xoodoo permutation state. + * + * \param state Xoodoo permutation state. + * \param phase Points to the current phase, up or down. + * \param data Points to the data to be absorbed. + * \param len Length of the data to be absorbed. + */ +static void xoodyak_absorb + (xoodoo_state_t *state, uint8_t *phase, + const unsigned char *data, unsigned long long len) +{ + uint8_t domain = 0x03; + unsigned temp; + while (len > XOODYAK_ABSORB_RATE) { + if (*phase != XOODYAK_PHASE_UP) + xoodoo_permute(state); + lw_xor_block(state->B, data, XOODYAK_ABSORB_RATE); + state->B[XOODYAK_ABSORB_RATE] ^= 0x01; /* Padding */ + state->B[sizeof(state->B) - 1] ^= domain; + data += XOODYAK_ABSORB_RATE; + len -= XOODYAK_ABSORB_RATE; + domain = 0x00; + *phase = XOODYAK_PHASE_DOWN; + } + temp = (unsigned)len; + if (*phase != XOODYAK_PHASE_UP) + xoodoo_permute(state); + lw_xor_block(state->B, data, temp); + state->B[temp] ^= 0x01; /* Padding */ + state->B[sizeof(state->B) - 1] ^= domain; + *phase = XOODYAK_PHASE_DOWN; +} + +int xoodyak_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) +{ + xoodoo_state_t state; + uint8_t phase, domain; + unsigned temp; + (void)nsec; + + /* Set the length of the returned ciphertext */ + *clen = mlen + XOODYAK_TAG_SIZE; + + /* Initialize the state with the key */ + memcpy(state.B, k, XOODYAK_KEY_SIZE); + memset(state.B + XOODYAK_KEY_SIZE, 0, sizeof(state.B) - XOODYAK_KEY_SIZE); + state.B[XOODYAK_KEY_SIZE + 1] = 0x01; /* Padding */ + state.B[sizeof(state.B) - 1] = 0x02; /* Domain separation */ + phase = XOODYAK_PHASE_DOWN; + + /* Absorb the nonce and associated data */ + xoodyak_absorb(&state, &phase, npub, XOODYAK_NONCE_SIZE); + xoodyak_absorb(&state, &phase, ad, adlen); + + /* Encrypt the plaintext to produce the ciphertext */ + domain = 0x80; + while (mlen > XOODYAK_SQUEEZE_RATE) { + state.B[sizeof(state.B) - 1] ^= domain; + xoodoo_permute(&state); + lw_xor_block_2_dest(c, state.B, m, XOODYAK_SQUEEZE_RATE); + state.B[XOODYAK_SQUEEZE_RATE] ^= 0x01; /* Padding */ + c += XOODYAK_SQUEEZE_RATE; + m += XOODYAK_SQUEEZE_RATE; + mlen -= XOODYAK_SQUEEZE_RATE; + domain = 0; + } + state.B[sizeof(state.B) - 1] ^= domain; + xoodoo_permute(&state); + temp = (unsigned)mlen; + lw_xor_block_2_dest(c, state.B, m, temp); + state.B[temp] ^= 0x01; /* Padding */ + c += temp; + + /* Generate the authentication tag */ + state.B[sizeof(state.B) - 1] ^= 0x40; /* Domain separation */ + xoodoo_permute(&state); + memcpy(c, state.B, XOODYAK_TAG_SIZE); + return 0; +} + +int xoodyak_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) +{ + xoodoo_state_t state; + uint8_t phase, domain; + unsigned temp; + unsigned char *mtemp = m; + (void)nsec; + + /* Validate the ciphertext length and set the return "mlen" value */ + if (clen < XOODYAK_TAG_SIZE) + return -1; + *mlen = clen - XOODYAK_TAG_SIZE; + + /* Initialize the state with the key */ + memcpy(state.B, k, XOODYAK_KEY_SIZE); + memset(state.B + XOODYAK_KEY_SIZE, 0, sizeof(state.B) - XOODYAK_KEY_SIZE); + state.B[XOODYAK_KEY_SIZE + 1] = 0x01; /* Padding */ + state.B[sizeof(state.B) - 1] = 0x02; /* Domain separation */ + phase = XOODYAK_PHASE_DOWN; + + /* Absorb the nonce and associated data */ + xoodyak_absorb(&state, &phase, npub, XOODYAK_NONCE_SIZE); + xoodyak_absorb(&state, &phase, ad, adlen); + + /* Decrypt the ciphertext to produce the plaintext */ + domain = 0x80; + clen -= XOODYAK_TAG_SIZE; + while (clen > XOODYAK_SQUEEZE_RATE) { + state.B[sizeof(state.B) - 1] ^= domain; + xoodoo_permute(&state); + lw_xor_block_swap(m, state.B, c, XOODYAK_SQUEEZE_RATE); + state.B[XOODYAK_SQUEEZE_RATE] ^= 0x01; /* Padding */ + c += XOODYAK_SQUEEZE_RATE; + m += XOODYAK_SQUEEZE_RATE; + clen -= XOODYAK_SQUEEZE_RATE; + domain = 0; + } + state.B[sizeof(state.B) - 1] ^= domain; + xoodoo_permute(&state); + temp = (unsigned)clen; + lw_xor_block_swap(m, state.B, c, temp); + state.B[temp] ^= 0x01; /* Padding */ + c += temp; + + /* Check the authentication tag */ + state.B[sizeof(state.B) - 1] ^= 0x40; /* Domain separation */ + xoodoo_permute(&state); + return aead_check_tag(mtemp, *mlen, state.B, c, XOODYAK_TAG_SIZE); +} + +int xoodyak_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen) +{ + xoodyak_hash_state_t state; + xoodyak_hash_init(&state); + xoodyak_hash_absorb(&state, in, inlen); + xoodyak_hash_squeeze(&state, out, XOODYAK_HASH_SIZE); + return 0; +} + +#define XOODYAK_HASH_MODE_INIT_ABSORB 0 +#define XOODYAK_HASH_MODE_ABSORB 1 +#define XOODYAK_HASH_MODE_SQUEEZE 2 + +#define xoodoo_hash_permute(state) \ + xoodoo_permute((xoodoo_state_t *)((state)->s.state)) + +void xoodyak_hash_init(xoodyak_hash_state_t *state) +{ + memset(state, 0, sizeof(xoodyak_hash_state_t)); + state->s.mode = XOODYAK_HASH_MODE_INIT_ABSORB; +} + +void xoodyak_hash_absorb + (xoodyak_hash_state_t *state, const unsigned char *in, + unsigned long long inlen) +{ + uint8_t domain; + unsigned temp; + + /* If we were squeezing, then restart the absorb phase */ + if (state->s.mode == XOODYAK_HASH_MODE_SQUEEZE) { + xoodoo_hash_permute(state); + state->s.mode = XOODYAK_HASH_MODE_INIT_ABSORB; + state->s.count = 0; + } + + /* The first block needs a different domain separator to the others */ + domain = (state->s.mode == XOODYAK_HASH_MODE_INIT_ABSORB) ? 0x01 : 0x00; + + /* Absorb the input data into the state */ + while (inlen > 0) { + if (state->s.count >= XOODYAK_HASH_RATE) { + state->s.state[XOODYAK_HASH_RATE] ^= 0x01; /* Padding */ + state->s.state[sizeof(state->s.state) - 1] ^= domain; + xoodoo_hash_permute(state); + state->s.mode = XOODYAK_HASH_MODE_ABSORB; + state->s.count = 0; + domain = 0x00; + } + temp = XOODYAK_HASH_RATE - state->s.count; + if (temp > inlen) + temp = (unsigned)inlen; + lw_xor_block(state->s.state + state->s.count, in, temp); + state->s.count += temp; + in += temp; + inlen -= temp; + } +} + +void xoodyak_hash_squeeze + (xoodyak_hash_state_t *state, unsigned char *out, + unsigned long long outlen) +{ + uint8_t domain; + unsigned temp; + + /* If we were absorbing, then terminate the absorb phase */ + if (state->s.mode != XOODYAK_HASH_MODE_SQUEEZE) { + domain = (state->s.mode == XOODYAK_HASH_MODE_INIT_ABSORB) ? 0x01 : 0x00; + state->s.state[state->s.count] ^= 0x01; /* Padding */ + state->s.state[sizeof(state->s.state) - 1] ^= domain; + xoodoo_hash_permute(state); + state->s.mode = XOODYAK_HASH_MODE_SQUEEZE; + state->s.count = 0; + } + + /* Squeeze data out of the state */ + while (outlen > 0) { + if (state->s.count >= XOODYAK_HASH_RATE) { + /* Padding is always at index 0 for squeezing subsequent + * blocks because the number of bytes we have absorbed + * since the previous block was squeezed out is zero */ + state->s.state[0] ^= 0x01; + xoodoo_hash_permute(state); + state->s.count = 0; + } + temp = XOODYAK_HASH_RATE - state->s.count; + if (temp > outlen) + temp = (unsigned)outlen; + memcpy(out, state->s.state + state->s.count, temp); + state->s.count += temp; + out += temp; + outlen -= temp; + } +} + +void xoodyak_hash_finalize + (xoodyak_hash_state_t *state, unsigned char *out) +{ + xoodyak_hash_squeeze(state, out, XOODYAK_HASH_SIZE); +} diff --git a/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.h b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.h new file mode 100644 index 0000000..f4777d5 --- /dev/null +++ b/xoodyak/Implementations/crypto_aead/xoodyakv1/rhys/xoodyak.h @@ -0,0 +1,226 @@ +/* + * 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_XOODYAK_H +#define LWCRYPTO_XOODYAK_H + +#include "aead-common.h" + +/** + * \file xoodyak.h + * \brief Xoodyak authenticated encryption algorithm. + * + * Xoodyak is an authenticated encryption and hash algorithm pair based + * around the 384-bit Xoodoo permutation that is similar in structure to + * Keccak but is more efficient than Keccak on 32-bit embedded devices. + * The Cyclist mode of operation is used to convert the permutation + * into a sponge for the higher-level algorithms. + * + * The Xoodyak encryption mode has a 128-bit key, a 128-bit nonce, + * and a 128-bit authentication tag. The Xoodyak hashing mode has a + * 256-bit fixed hash output and can also be used as an extensible + * output function (XOF). + * + * The Xoodyak specification describes a re-keying mechanism where the + * key for one packet is used to derive the key to use on the next packet. + * This provides some resistance against side channel attacks by making + * the session key a moving target. This library does not currently + * implement re-keying. + * + * References: https://keccak.team/xoodyak.html + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Size of the key for Xoodyak. + */ +#define XOODYAK_KEY_SIZE 16 + +/** + * \brief Size of the authentication tag for Xoodyak. + */ +#define XOODYAK_TAG_SIZE 16 + +/** + * \brief Size of the nonce for Xoodyak. + */ +#define XOODYAK_NONCE_SIZE 16 + +/** + * \brief Size of the hash output for Xoodyak. + */ +#define XOODYAK_HASH_SIZE 32 + +/** + * \brief State information for Xoodyak incremental hashing modes. + */ +typedef union +{ + struct { + unsigned char state[48]; /**< Current hash state */ + unsigned char count; /**< Number of bytes in the current block */ + unsigned char mode; /**< Hash mode: absorb or squeeze */ + } s; /**< State */ + unsigned long long align; /**< For alignment of this structure */ + +} xoodyak_hash_state_t; + +/** + * \brief Meta-information block for the Xoodyak cipher. + */ +extern aead_cipher_t const xoodyak_cipher; + +/** + * \brief Meta-information block for the Xoodyak hash algorithm. + */ +extern aead_hash_algorithm_t const xoodyak_hash_algorithm; + +/** + * \brief Encrypts and authenticates a packet with Xoodyak. + * + * \param c Buffer to receive the output. + * \param clen On exit, set to the length of the output which includes + * the ciphertext and the 16 byte 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 - not used by this algorithm. + * \param npub Points to the public nonce for the packet which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of the key to use to encrypt the packet. + * + * \return 0 on success, or a negative value if there was an error in + * the parameters. + * + * \sa xoodyak_aead_decrypt() + */ +int xoodyak_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); + +/** + * \brief Decrypts and authenticates a packet with Xoodyak. + * + * \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 - not used by this algorithm. + * \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 16 byte 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 which must + * be 16 bytes in length. + * \param k Points to the 16 bytes of 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. + * + * \sa xoodyak_aead_encrypt() + */ +int xoodyak_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); + +/** + * \brief Hashes a block of input data with Xoodyak to generate a hash value. + * + * \param out Buffer to receive the hash output which must be at least + * XOODYAK_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 xoodyak_hash + (unsigned char *out, const unsigned char *in, unsigned long long inlen); + +/** + * \brief Initializes the state for a Xoodyak hashing operation. + * + * \param state Hash state to be initialized. + * + * \sa xoodyak_hash_absorb(), xoodyak_hash_squeeze(), xoodyak_hash() + */ +void xoodyak_hash_init(xoodyak_hash_state_t *state); + +/** + * \brief Aborbs more input data into a Xoodyak hashing state. + * + * \param state Hash 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 xoodyak_hash_init(), xoodyak_hash_squeeze() + */ +void xoodyak_hash_absorb + (xoodyak_hash_state_t *state, const unsigned char *in, + unsigned long long inlen); + +/** + * \brief Squeezes output data from a Xoodyak hashing state. + * + * \param state Hash 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. + * + * \sa xoodyak_hash_init(), xoodyak_hash_absorb() + */ +void xoodyak_hash_squeeze + (xoodyak_hash_state_t *state, unsigned char *out, + unsigned long long outlen); + +/** + * \brief Returns the final hash value from a Xoodyak hashing operation. + * + * \param state Hash state to be finalized. + * \param out Points to the output buffer to receive the hash value. + * + * \note This is a wrapper around xoodyak_hash_squeeze() for a fixed length + * of XOODYAK_HASH_SIZE bytes. + * + * \sa xoodyak_hash_init(), xoodyak_hash_absorb() + */ +void xoodyak_hash_finalize + (xoodyak_hash_state_t *state, unsigned char *out); + +#ifdef __cplusplus +} +#endif + +#endif