Commit 7d44261a by Enrico Pozzobon

Merge branch 'patched-for-tester' of lab.las3.de:lwc/candidates into patched-for-tester

parents c2960695 b6e4586f
......@@ -52,23 +52,6 @@ static void hyena_double_delta(unsigned char D[8])
}
/**
* \brief Triples a delta value in the F(2^64) field.
*
* \param D The delta value to be tripled.
*
* D' = D ^ (D << 1) if the top-most bit is 0, or D' = D ^ (D << 1) ^ 0x1B
* otherwise.
*/
static void hyena_triple_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.
......@@ -83,26 +66,27 @@ static void hyena_process_ad
unsigned long long adlen)
{
unsigned char feedback[16];
hyena_double_delta(D);
while (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);
gift128n_encrypt(ks, Y, Y);
hyena_double_delta(D);
ad += 16;
adlen -= 16;
}
if (adlen == 16) {
hyena_triple_delta(D);
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_triple_delta(D);
hyena_triple_delta(D);
hyena_double_delta(D);
hyena_double_delta(D);
memcpy(feedback, ad, temp);
feedback[temp] = 0x01;
memset(feedback + temp + 1, 0, 15 - temp);
......@@ -132,7 +116,8 @@ int hyena_aead_encrypt
*clen = mlen + HYENA_TAG_SIZE;
/* Set up the key schedule and use it to encrypt the nonce */
gift128n_init(&ks, k);
if (!gift128n_init(&ks, k, HYENA_KEY_SIZE))
return -1;
Y[0] = 0;
if (adlen == 0)
Y[0] |= 0x01;
......@@ -164,7 +149,8 @@ int hyena_aead_encrypt
}
gift128n_encrypt(&ks, Y, Y);
if (mlen == 16) {
hyena_triple_delta(D);
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);
......@@ -173,8 +159,9 @@ int hyena_aead_encrypt
c += 16;
} else {
unsigned temp = (unsigned)mlen;
hyena_triple_delta(D);
hyena_triple_delta(D);
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);
......@@ -220,7 +207,8 @@ int hyena_aead_decrypt
*mlen = clen - HYENA_TAG_SIZE;
/* Set up the key schedule and use it to encrypt the nonce */
gift128n_init(&ks, k);
if (!gift128n_init(&ks, k, HYENA_KEY_SIZE))
return -1;
Y[0] = 0;
if (adlen == 0)
Y[0] |= 0x01;
......@@ -254,7 +242,8 @@ int hyena_aead_decrypt
}
gift128n_encrypt(&ks, Y, Y);
if (clen == 16) {
hyena_triple_delta(D);
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);
......@@ -263,8 +252,9 @@ int hyena_aead_decrypt
c += 16;
} else {
unsigned temp = (unsigned)clen;
hyena_triple_delta(D);
hyena_triple_delta(D);
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);
......
......@@ -47,13 +47,11 @@
* 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://eprint.iacr.org/2020/412.pdf,
* https://giftcipher.github.io/gift/
*/
#include <stddef.h>
#include <stdint.h>
#include "internal-gift128-config.h"
#ifdef __cplusplus
extern "C" {
......@@ -65,23 +63,16 @@ extern "C" {
#define GIFT128_BLOCK_SIZE 16
/**
* \var GIFT128_ROUND_KEYS
* \brief Number of round keys for the GIFT-128 key schedule.
* \brief Number of round keys for the fixsliced representation of GIFT-128.
*/
#if GIFT128_VARIANT == GIFT128_VARIANT_TINY
#define GIFT128_ROUND_KEYS 4
#elif GIFT128_VARIANT == GIFT128_VARIANT_SMALL
#define GIFT128_ROUND_KEYS 20
#else
#define GIFT128_ROUND_KEYS 80
#endif
/**
* \brief Structure of the key schedule for GIFT-128 (bit-sliced).
*/
typedef struct
{
/** Pre-computed round keys for bit-sliced GIFT-128 */
/** Pre-computed round keys in the fixsliced form */
uint32_t k[GIFT128_ROUND_KEYS];
} gift128b_key_schedule_t;
......@@ -90,9 +81,14 @@ typedef struct
* \brief Initializes the key schedule for GIFT-128 (bit-sliced).
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the 16 bytes of the key data.
* \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.
*/
void gift128b_init(gift128b_key_schedule_t *ks, const unsigned char *key);
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).
......@@ -149,9 +145,14 @@ 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 16 bytes of the key data.
* \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.
*/
void gift128n_init(gift128n_key_schedule_t *ks, const unsigned char *key);
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).
......@@ -181,31 +182,13 @@ void gift128n_decrypt
(const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input);
/* 4-bit tweak values expanded to 32-bit for TweGIFT-128 */
#define GIFT128T_TWEAK_0 0x00000000 /**< TweGIFT-128 tweak value 0 */
#define GIFT128T_TWEAK_1 0xe1e1e1e1 /**< TweGIFT-128 tweak value 1 */
#define GIFT128T_TWEAK_2 0xd2d2d2d2 /**< TweGIFT-128 tweak value 2 */
#define GIFT128T_TWEAK_3 0x33333333 /**< TweGIFT-128 tweak value 3 */
#define GIFT128T_TWEAK_4 0xb4b4b4b4 /**< TweGIFT-128 tweak value 4 */
#define GIFT128T_TWEAK_5 0x55555555 /**< TweGIFT-128 tweak value 5 */
#define GIFT128T_TWEAK_6 0x66666666 /**< TweGIFT-128 tweak value 6 */
#define GIFT128T_TWEAK_7 0x87878787 /**< TweGIFT-128 tweak value 7 */
#define GIFT128T_TWEAK_8 0x78787878 /**< TweGIFT-128 tweak value 8 */
#define GIFT128T_TWEAK_9 0x99999999 /**< TweGIFT-128 tweak value 9 */
#define GIFT128T_TWEAK_10 0xaaaaaaaa /**< TweGIFT-128 tweak value 10 */
#define GIFT128T_TWEAK_11 0x4b4b4b4b /**< TweGIFT-128 tweak value 11 */
#define GIFT128T_TWEAK_12 0xcccccccc /**< TweGIFT-128 tweak value 12 */
#define GIFT128T_TWEAK_13 0x2d2d2d2d /**< TweGIFT-128 tweak value 13 */
#define GIFT128T_TWEAK_14 0x1e1e1e1e /**< TweGIFT-128 tweak value 14 */
#define GIFT128T_TWEAK_15 0xffffffff /**< TweGIFT-128 tweak value 15 */
/**
* \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 expanded to 32-bit.
* \param tweak 4-bit tweak value.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
......@@ -217,7 +200,7 @@ void gift128n_decrypt
*/
void gift128t_encrypt
(const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, uint32_t tweak);
const unsigned char *input, unsigned char tweak);
/**
* \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant).
......@@ -225,7 +208,7 @@ void gift128t_encrypt
* \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 expanded to 32-bit.
* \param tweak 4-bit tweak value.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
......@@ -237,7 +220,7 @@ void gift128t_encrypt
*/
void gift128t_decrypt
(const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, uint32_t tweak);
const unsigned char *input, unsigned char tweak);
#ifdef __cplusplus
}
......
......@@ -238,17 +238,6 @@
} \
} while (0)
/* Rotation functions need to be optimised for best performance on AVR.
* The most efficient rotations are where the number of bits is 1 or a
* multiple of 8, so we compose the efficient rotations to produce all
* other rotation counts of interest. */
#if defined(__AVR__)
#define LW_CRYPTO_ROTATE32_COMPOSED 1
#else
#define LW_CRYPTO_ROTATE32_COMPOSED 0
#endif
/* Rotation macros for 32-bit arguments */
/* Generic left rotate */
......@@ -265,8 +254,6 @@
(_temp >> (bits)) | (_temp << (32 - (bits))); \
}))
#if !LW_CRYPTO_ROTATE32_COMPOSED
/* Left rotate 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))
......@@ -335,138 +322,6 @@
#define rightRotate30(a) (rightRotate((a), 30))
#define rightRotate31(a) (rightRotate((a), 31))
#else /* LW_CRYPTO_ROTATE32_COMPOSED */
/* Composed rotation macros where 1 and 8 are fast, but others are slow */
/* Left rotate by 1 */
#define leftRotate1(a) (leftRotate((a), 1))
/* Left rotate by 2 */
#define leftRotate2(a) (leftRotate(leftRotate((a), 1), 1))
/* Left rotate by 3 */
#define leftRotate3(a) (leftRotate(leftRotate(leftRotate((a), 1), 1), 1))
/* Left rotate by 4 */
#define leftRotate4(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 1), 1), 1), 1))
/* Left rotate by 5: Rotate left by 8, then right by 3 */
#define leftRotate5(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 8), 1), 1), 1))
/* Left rotate by 6: Rotate left by 8, then right by 2 */
#define leftRotate6(a) (rightRotate(rightRotate(leftRotate((a), 8), 1), 1))
/* Left rotate by 7: Rotate left by 8, then right by 1 */
#define leftRotate7(a) (rightRotate(leftRotate((a), 8), 1))
/* Left rotate by 8 */
#define leftRotate8(a) (leftRotate((a), 8))
/* Left rotate by 9: Rotate left by 8, then left by 1 */
#define leftRotate9(a) (leftRotate(leftRotate((a), 8), 1))
/* Left rotate by 10: Rotate left by 8, then left by 2 */
#define leftRotate10(a) (leftRotate(leftRotate(leftRotate((a), 8), 1), 1))
/* Left rotate by 11: Rotate left by 8, then left by 3 */
#define leftRotate11(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 8), 1), 1), 1))
/* Left rotate by 12: Rotate left by 16, then right by 4 */
#define leftRotate12(a) (rightRotate(rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1), 1))
/* Left rotate by 13: Rotate left by 16, then right by 3 */
#define leftRotate13(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1))
/* Left rotate by 14: Rotate left by 16, then right by 2 */
#define leftRotate14(a) (rightRotate(rightRotate(leftRotate((a), 16), 1), 1))
/* Left rotate by 15: Rotate left by 16, then right by 1 */
#define leftRotate15(a) (rightRotate(leftRotate((a), 16), 1))
/* Left rotate by 16 */
#define leftRotate16(a) (leftRotate((a), 16))
/* Left rotate by 17: Rotate left by 16, then left by 1 */
#define leftRotate17(a) (leftRotate(leftRotate((a), 16), 1))
/* Left rotate by 18: Rotate left by 16, then left by 2 */
#define leftRotate18(a) (leftRotate(leftRotate(leftRotate((a), 16), 1), 1))
/* Left rotate by 19: Rotate left by 16, then left by 3 */
#define leftRotate19(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1))
/* Left rotate by 20: Rotate left by 16, then left by 4 */
#define leftRotate20(a) (leftRotate(leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1), 1))
/* Left rotate by 21: Rotate left by 24, then right by 3 */
#define leftRotate21(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 24), 1), 1), 1))
/* Left rotate by 22: Rotate left by 24, then right by 2 */
#define leftRotate22(a) (rightRotate(rightRotate(leftRotate((a), 24), 1), 1))
/* Left rotate by 23: Rotate left by 24, then right by 1 */
#define leftRotate23(a) (rightRotate(leftRotate((a), 24), 1))
/* Left rotate by 24 */
#define leftRotate24(a) (leftRotate((a), 24))
/* Left rotate by 25: Rotate left by 24, then left by 1 */
#define leftRotate25(a) (leftRotate(leftRotate((a), 24), 1))
/* Left rotate by 26: Rotate left by 24, then left by 2 */
#define leftRotate26(a) (leftRotate(leftRotate(leftRotate((a), 24), 1), 1))
/* Left rotate by 27: Rotate left by 24, then left by 3 */
#define leftRotate27(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 24), 1), 1), 1))
/* Left rotate by 28: Rotate right by 4 */
#define leftRotate28(a) (rightRotate(rightRotate(rightRotate(rightRotate((a), 1), 1), 1), 1))
/* Left rotate by 29: Rotate right by 3 */
#define leftRotate29(a) (rightRotate(rightRotate(rightRotate((a), 1), 1), 1))
/* Left rotate by 30: Rotate right by 2 */
#define leftRotate30(a) (rightRotate(rightRotate((a), 1), 1))
/* Left rotate by 31: Rotate right by 1 */
#define leftRotate31(a) (rightRotate((a), 1))
/* Define the 32-bit right rotations in terms of left rotations */
#define rightRotate1(a) (leftRotate31((a)))
#define rightRotate2(a) (leftRotate30((a)))
#define rightRotate3(a) (leftRotate29((a)))
#define rightRotate4(a) (leftRotate28((a)))
#define rightRotate5(a) (leftRotate27((a)))
#define rightRotate6(a) (leftRotate26((a)))
#define rightRotate7(a) (leftRotate25((a)))
#define rightRotate8(a) (leftRotate24((a)))
#define rightRotate9(a) (leftRotate23((a)))
#define rightRotate10(a) (leftRotate22((a)))
#define rightRotate11(a) (leftRotate21((a)))
#define rightRotate12(a) (leftRotate20((a)))
#define rightRotate13(a) (leftRotate19((a)))
#define rightRotate14(a) (leftRotate18((a)))
#define rightRotate15(a) (leftRotate17((a)))
#define rightRotate16(a) (leftRotate16((a)))
#define rightRotate17(a) (leftRotate15((a)))
#define rightRotate18(a) (leftRotate14((a)))
#define rightRotate19(a) (leftRotate13((a)))
#define rightRotate20(a) (leftRotate12((a)))
#define rightRotate21(a) (leftRotate11((a)))
#define rightRotate22(a) (leftRotate10((a)))
#define rightRotate23(a) (leftRotate9((a)))
#define rightRotate24(a) (leftRotate8((a)))
#define rightRotate25(a) (leftRotate7((a)))
#define rightRotate26(a) (leftRotate6((a)))
#define rightRotate27(a) (leftRotate5((a)))
#define rightRotate28(a) (leftRotate4((a)))
#define rightRotate29(a) (leftRotate3((a)))
#define rightRotate30(a) (leftRotate2((a)))
#define rightRotate31(a) (leftRotate1((a)))
#endif /* LW_CRYPTO_ROTATE32_COMPOSED */
/* Rotation macros for 64-bit arguments */
/* Generic left rotate */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "aead-common.h"
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = (accum - 1) >> 8;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size, int precheck)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = ((accum - 1) >> 8) & precheck;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LWCRYPTO_AEAD_COMMON_H
#define LWCRYPTO_AEAD_COMMON_H
#include <stddef.h>
/**
* \file aead-common.h
* \brief Definitions that are common across AEAD schemes.
*
* AEAD stands for "Authenticated Encryption with Associated Data".
* It is a standard API pattern for securely encrypting and
* authenticating packets of data.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Encrypts and authenticates a packet with an AEAD scheme.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the authentication tag.
* \param m Buffer that contains the plaintext message to encrypt.
* \param mlen Length of the plaintext message in bytes.
* \param ad Buffer that contains associated data to authenticate
* along with the packet but which does not need to be encrypted.
* \param adlen Length of the associated data in bytes.
* \param nsec Secret nonce - normally not used by AEAD schemes.
* \param npub Points to the public nonce for the packet.
* \param k Points to the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*/
typedef int (*aead_cipher_encrypt_t)
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with an AEAD scheme.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \param nsec Secret nonce - normally not used by AEAD schemes.
* \param c Buffer that contains the ciphertext and authentication
* tag to decrypt.
* \param clen Length of the input data in bytes, which includes the
* ciphertext and the authentication tag.
* \param ad Buffer that contains associated data to authenticate
* along with the packet but which does not need to be encrypted.
* \param adlen Length of the associated data in bytes.
* \param npub Points to the public nonce for the packet.
* \param k Points to the key to use to decrypt the packet.
*
* \return 0 on success, -1 if the authentication tag was incorrect,
* or some other negative number if there was an error in the parameters.
*/
typedef int (*aead_cipher_decrypt_t)
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c, unsigned long long clen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Hashes a block of input data.
*
* \param out Buffer to receive the hash output.
* \param in Points to the input data to be hashed.
* \param inlen Length of the input data in bytes.
*
* \return Returns zero on success or -1 if there was an error in the
* parameters.
*/
typedef int (*aead_hash_t)
(unsigned char *out, const unsigned char *in, unsigned long long inlen);
/**
* \brief Initializes the state for a hashing operation.
*
* \param state Hash state to be initialized.
*/
typedef void (*aead_hash_init_t)(void *state);
/**
* \brief Updates a hash state with more input data.
*
* \param state Hash state to be updated.
* \param in Points to the input data to be incorporated into the state.
* \param inlen Length of the input data to be incorporated into the state.
*/
typedef void (*aead_hash_update_t)
(void *state, const unsigned char *in, unsigned long long inlen);
/**
* \brief Returns the final hash value from a hashing operation.
*
* \param Hash state to be finalized.
* \param out Points to the output buffer to receive the hash value.
*/
typedef void (*aead_hash_finalize_t)(void *state, unsigned char *out);
/**
* \brief Aborbs more input data into an XOF state.
*
* \param state XOF state to be updated.
* \param in Points to the input data to be absorbed into the state.
* \param inlen Length of the input data to be absorbed into the state.
*
* \sa ascon_xof_init(), ascon_xof_squeeze()
*/
typedef void (*aead_xof_absorb_t)
(void *state, const unsigned char *in, unsigned long long inlen);
/**
* \brief Squeezes output data from an XOF state.
*
* \param state XOF state to squeeze the output data from.
* \param out Points to the output buffer to receive the squeezed data.
* \param outlen Number of bytes of data to squeeze out of the state.
*/
typedef void (*aead_xof_squeeze_t)
(void *state, unsigned char *out, unsigned long long outlen);
/**
* \brief No special AEAD features.
*/
#define AEAD_FLAG_NONE 0x0000
/**
* \brief The natural byte order of the AEAD cipher is little-endian.
*
* If this flag is not present, then the natural byte order of the
* AEAD cipher should be assumed to be big-endian.
*
* The natural byte order may be useful when formatting packet sequence
* numbers as nonces. The application needs to know whether the sequence
* number should be packed into the leading or trailing bytes of the nonce.
*/
#define AEAD_FLAG_LITTLE_ENDIAN 0x0001
/**
* \brief Meta-information about an AEAD cipher.
*/
typedef struct
{
const char *name; /**< Name of the cipher */
unsigned key_len; /**< Length of the key in bytes */
unsigned nonce_len; /**< Length of the nonce in bytes */
unsigned tag_len; /**< Length of the tag in bytes */
unsigned flags; /**< Flags for extra features */
aead_cipher_encrypt_t encrypt; /**< AEAD encryption function */
aead_cipher_decrypt_t decrypt; /**< AEAD decryption function */
} aead_cipher_t;
/**
* \brief Meta-information about a hash algorithm that is related to an AEAD.
*
* Regular hash algorithms should provide the "hash", "init", "update",
* and "finalize" functions. Extensible Output Functions (XOF's) should
* proivde the "hash", "init", "absorb", and "squeeze" functions.
*/
typedef struct
{
const char *name; /**< Name of the hash algorithm */
size_t state_size; /**< Size of the incremental state structure */
unsigned hash_len; /**< Length of the hash in bytes */
unsigned flags; /**< Flags for extra features */
aead_hash_t hash; /**< All in one hashing function */
aead_hash_init_t init; /**< Incremental hash/XOF init function */
aead_hash_update_t update; /**< Incremental hash update function */
aead_hash_finalize_t finalize; /**< Incremental hash finalize function */
aead_xof_absorb_t absorb; /**< Incremental XOF absorb function */
aead_xof_squeeze_t squeeze; /**< Incremental XOF squeeze function */
} aead_hash_algorithm_t;
/**
* \brief Check an authentication tag in constant time.
*
* \param plaintext Points to the plaintext data.
* \param plaintext_len Length of the plaintext in bytes.
* \param tag1 First tag to compare.
* \param tag2 Second tag to compare.
* \param tag_len Length of the tags in bytes.
*
* \return Returns -1 if the tag check failed or 0 if the check succeeded.
*
* If the tag check fails, then the \a plaintext will also be zeroed to
* prevent it from being used accidentally by the application when the
* ciphertext was invalid.
*/
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned tag_len);
/**
* \brief Check an authentication tag in constant time with a previous check.
*
* \param plaintext Points to the plaintext data.
* \param plaintext_len Length of the plaintext in bytes.
* \param tag1 First tag to compare.
* \param tag2 Second tag to compare.
* \param tag_len Length of the tags in bytes.
* \param precheck Set to -1 if previous check succeeded or 0 if it failed.
*
* \return Returns -1 if the tag check failed or 0 if the check succeeded.
*
* If the tag check fails, then the \a plaintext will also be zeroed to
* prevent it from being used accidentally by the application when the
* ciphertext was invalid.
*
* This version can be used to incorporate other information about the
* correctness of the plaintext into the final result.
*/
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned tag_len, int precheck);
#ifdef __cplusplus
}
#endif
#endif
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 12
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#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);
}
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION 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 <string.h>
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 Triples a delta value in the F(2^64) field.
*
* \param D The delta value to be tripled.
*
* D' = D ^ (D << 1) if the top-most bit is 0, or D' = D ^ (D << 1) ^ 0x1B
* otherwise.
*/
static void hyena_triple_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];
while (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);
gift128n_encrypt(ks, Y, Y);
ad += 16;
adlen -= 16;
}
if (adlen == 16) {
hyena_triple_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_triple_delta(D);
hyena_triple_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 */
gift128n_init(&ks, k);
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_triple_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_triple_delta(D);
hyena_triple_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 */
gift128n_init(&ks, k);
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_triple_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_triple_delta(D);
hyena_triple_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);
}
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF 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
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF 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_CONFIG_H
#define LW_INTERNAL_GIFT128_CONFIG_H
/**
* \file internal-gift128-config.h
* \brief Configures the variant of GIFT-128 to use.
*/
/**
* \brief Select the full variant of GIFT-128.
*
* The full variant requires 320 bytes for the key schedule and uses the
* fixslicing method to implement encryption and decryption.
*/
#define GIFT128_VARIANT_FULL 0
/**
* \brief Select the small variant of GIFT-128.
*
* The small variant requires 80 bytes for the key schedule. The rest
* of the key schedule is expanded on the fly during encryption.
*
* The fixslicing method is used to implement encryption and the slower
* bitslicing method is used to implement decryption. The small variant
* is suitable when memory is at a premium, decryption is not needed,
* but encryption performance is still important.
*/
#define GIFT128_VARIANT_SMALL 1
/**
* \brief Select the tiny variant of GIFT-128.
*
* The tiny variant requires 16 bytes for the key schedule and uses the
* bitslicing method to implement encryption and decryption. It is suitable
* for use when memory is very tight and performance is not critical.
*/
#define GIFT128_VARIANT_TINY 2
/**
* \def GIFT128_VARIANT
* \brief Selects the default variant of GIFT-128 to use on this platform.
*/
/**
* \def GIFT128_VARIANT_ASM
* \brief Defined to 1 if the GIFT-128 implementation has been replaced
* with an assembly code version.
*/
#if defined(__AVR__) && !defined(GIFT128_VARIANT_ASM)
#define GIFT128_VARIANT_ASM 1
#endif
#if !defined(GIFT128_VARIANT)
#define GIFT128_VARIANT GIFT128_VARIANT_FULL
#endif
#if !defined(GIFT128_VARIANT_ASM)
#define GIFT128_VARIANT_ASM 0
#endif
#endif
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#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://eprint.iacr.org/2020/412.pdf,
* https://giftcipher.github.io/gift/
*/
#include <stddef.h>
#include <stdint.h>
#include "internal-gift128-config.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of a GIFT-128 block in bytes.
*/
#define GIFT128_BLOCK_SIZE 16
/**
* \var GIFT128_ROUND_KEYS
* \brief Number of round keys for the GIFT-128 key schedule.
*/
#if GIFT128_VARIANT == GIFT128_VARIANT_TINY
#define GIFT128_ROUND_KEYS 4
#elif GIFT128_VARIANT == GIFT128_VARIANT_SMALL
#define GIFT128_ROUND_KEYS 20
#else
#define GIFT128_ROUND_KEYS 80
#endif
/**
* \brief Structure of the key schedule for GIFT-128 (bit-sliced).
*/
typedef struct
{
/** Pre-computed round keys for bit-sliced GIFT-128 */
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 16 bytes of the key data.
*/
void gift128b_init(gift128b_key_schedule_t *ks, const unsigned char *key);
/**
* \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 16 bytes of the key data.
*/
void gift128n_init(gift128n_key_schedule_t *ks, const unsigned char *key);
/**
* \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);
/* 4-bit tweak values expanded to 32-bit for TweGIFT-128 */
#define GIFT128T_TWEAK_0 0x00000000 /**< TweGIFT-128 tweak value 0 */
#define GIFT128T_TWEAK_1 0xe1e1e1e1 /**< TweGIFT-128 tweak value 1 */
#define GIFT128T_TWEAK_2 0xd2d2d2d2 /**< TweGIFT-128 tweak value 2 */
#define GIFT128T_TWEAK_3 0x33333333 /**< TweGIFT-128 tweak value 3 */
#define GIFT128T_TWEAK_4 0xb4b4b4b4 /**< TweGIFT-128 tweak value 4 */
#define GIFT128T_TWEAK_5 0x55555555 /**< TweGIFT-128 tweak value 5 */
#define GIFT128T_TWEAK_6 0x66666666 /**< TweGIFT-128 tweak value 6 */
#define GIFT128T_TWEAK_7 0x87878787 /**< TweGIFT-128 tweak value 7 */
#define GIFT128T_TWEAK_8 0x78787878 /**< TweGIFT-128 tweak value 8 */
#define GIFT128T_TWEAK_9 0x99999999 /**< TweGIFT-128 tweak value 9 */
#define GIFT128T_TWEAK_10 0xaaaaaaaa /**< TweGIFT-128 tweak value 10 */
#define GIFT128T_TWEAK_11 0x4b4b4b4b /**< TweGIFT-128 tweak value 11 */
#define GIFT128T_TWEAK_12 0xcccccccc /**< TweGIFT-128 tweak value 12 */
#define GIFT128T_TWEAK_13 0x2d2d2d2d /**< TweGIFT-128 tweak value 13 */
#define GIFT128T_TWEAK_14 0x1e1e1e1e /**< TweGIFT-128 tweak value 14 */
#define GIFT128T_TWEAK_15 0xffffffff /**< TweGIFT-128 tweak value 15 */
/**
* \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 expanded to 32-bit.
*
* 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, uint32_t 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 expanded to 32-bit.
*
* 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, uint32_t tweak);
#ifdef __cplusplus
}
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment