Commit a2add83a by Rhys Weatherley Committed by Enrico Pozzobon

new optimized implementations

parent 6a3941ac
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef LW_INTERNAL_FORKSKINNY_H #ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H #define LW_INTERNAL_FORKSKINNY_H
#include "internal-util.h"
/** /**
* \file internal-forkskinny.h * \file internal-forkskinny.h
* \brief ForkSkinny block cipher family. * \brief ForkSkinny block cipher family.
...@@ -39,6 +41,158 @@ extern "C" { ...@@ -39,6 +41,158 @@ extern "C" {
#endif #endif
/** /**
* \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 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 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 several rounds of ForkSkinny-128-256.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_256_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-256 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_256_inv_rounds
(forkskinny_128_256_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_256_forward_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-256.
*
* \param state Points to the ForkSkinny-128-256 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_256_reverse_tk
(forkskinny_128_256_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-128-384.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*/
void forkskinny_128_384_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-128-384 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_128_384_inv_rounds
(forkskinny_128_384_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_128_384_forward_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-128-384.
*
* \param state Points to the ForkSkinny-128-384 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_128_384_reverse_tk
(forkskinny_128_384_state_t *state, unsigned rounds);
/**
* \brief Applies several rounds of ForkSkinny-64-192.
*
* \param state State to apply the rounds to.
* \param first First round to apply.
* \param last Last round to apply plus 1.
*
* Note: The cells of each row are ordered in big-endian nibble order
* so it is simplest to manage the rows in big-endian byte order.
*/
void forkskinny_64_192_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Applies several rounds of ForkSkinny-64-192 in reverse.
*
* \param state State to apply the rounds to.
* \param first First round to apply plus 1.
* \param last Last round to apply.
*/
void forkskinny_64_192_inv_rounds
(forkskinny_64_192_state_t *state, unsigned first, unsigned last);
/**
* \brief Forwards the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to forward by.
*/
void forkskinny_64_192_forward_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Reverses the tweakey for ForkSkinny-64-192.
*
* \param state Points to the ForkSkinny-64-192 state.
* \param rounds Number of rounds to reverse by.
*/
void forkskinny_64_192_reverse_tk
(forkskinny_64_192_state_t *state, unsigned rounds);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256. * \brief Encrypts a block of plaintext with ForkSkinny-128-256.
* *
* \param key 256-bit tweakey for ForkSkinny-128-256. * \param key 256-bit tweakey for ForkSkinny-128-256.
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
* combination of a 128-bit linear feedback shift register (LFSR) and 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 * 128-bit non-linear feedback shift register (NFSR). It is a member of
* the Grain family of stream ciphers. * the Grain family of stream ciphers.
*
* References: https://grain-128aead.github.io/
*/ */
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -26,14 +26,9 @@ ...@@ -26,14 +26,9 @@
#define GWORD(a, b, start_bit) \ #define GWORD(a, b, start_bit) \
(((a) << ((start_bit) % 32)) ^ ((b) >> (32 - ((start_bit) % 32)))) (((a) << ((start_bit) % 32)) ^ ((b) >> (32 - ((start_bit) % 32))))
/** #if !defined(__AVR__)
* \brief Performs 32 rounds of Grain-128 in parallel.
* void grain128_core
* \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) (grain128_state_t *state, uint32_t x, uint32_t x2)
{ {
uint32_t s0, s1, s2, s3; uint32_t s0, s1, s2, s3;
...@@ -67,7 +62,7 @@ static void grain128_core ...@@ -67,7 +62,7 @@ static void grain128_core
/* Perform the NFSR feedback algorithm from the specification: /* Perform the NFSR feedback algorithm from the specification:
* *
* b'[i] = b[i + 1] * b'[i] = b[i + 1]
* b'[127] = s'[127] ^ b[0] ^ b[26] ^ b[56] ^ b[91] ^ b[96] * b'[127] = s[0] ^ b[0] ^ b[26] ^ b[56] ^ b[91] ^ b[96]
* ^ (b[3] & b[67]) ^ (b[11] & b[13]) ^ (b[17] & b[18]) * ^ (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[27] & b[59]) ^ (b[40] & b[48]) ^ (b[61] & b[65])
* ^ (b[68] & b[84]) ^ (b[22] & b[24] & b[25]) * ^ (b[68] & b[84]) ^ (b[22] & b[24] & b[25])
...@@ -106,14 +101,19 @@ static void grain128_core ...@@ -106,14 +101,19 @@ static void grain128_core
state->nfsr[3] = x2; state->nfsr[3] = x2;
} }
/** #define grain128_preoutput grain128_preoutput_inner
* \brief Generates 32 bits of pre-output data. #define grain128_preoutput_setup(state) grain128_preoutput((state))
*
* \param state Grain-128 state. #else /* __AVR__ */
*
* \return The generated 32 bits of pre-output data. /* For some reason, the AVR assembly preoutput doesn't work for key setup
*/ * but does work everywhere else. Investigate and fix this later. */
static uint32_t grain128_preoutput(const grain128_state_t *state) uint32_t grain128_preoutput(const grain128_state_t *state);
#define grain128_preoutput_setup(state) grain128_preoutput_inner((state))
#endif /* __AVR__ */
uint32_t grain128_preoutput_inner(const grain128_state_t *state)
{ {
uint32_t s0, s1, s2, s3; uint32_t s0, s1, s2, s3;
uint32_t b0, b1, b2, b3; uint32_t b0, b1, b2, b3;
...@@ -170,12 +170,37 @@ static uint32_t grain128_preoutput(const grain128_state_t *state) ...@@ -170,12 +170,37 @@ static uint32_t grain128_preoutput(const grain128_state_t *state)
(_y) = (((_y) & (mask)) << (shift)) | (((_y) >> (shift)) & (mask)); \ (_y) = (((_y) & (mask)) << (shift)) | (((_y) >> (shift)) & (mask)); \
} while (0) } while (0)
#if defined(__AVR__)
#define GRAIN128_ASM_HELPERS 1
#endif
#if defined(GRAIN128_ASM_HELPERS)
/**
* \brief Loads a 32-bit word and swaps it from big-endian bit order
* into little-endian bit order.
*
* \param data Points to the word to be loaded.
* \return Little-endian version of the 32-bit word at \a data.
*/
uint32_t grain128_swap_word32(const unsigned char *data);
/**
* \brief Interleaves the bits in a 16-byte keystream block to separate
* out the even and odd bits.
*
* \param ks Points to the keystream block.
*/
void grain128_interleave(unsigned char *ks);
#endif
void grain128_setup void grain128_setup
(grain128_state_t *state, const unsigned char *key, (grain128_state_t *state, const unsigned char *key,
const unsigned char *nonce) const unsigned char *nonce)
{ {
uint32_t k[4]; uint32_t k[4];
unsigned round; uint8_t round;
/* Internally, the Grain-128 stream cipher uses big endian bit /* Internally, the Grain-128 stream cipher uses big endian bit
* order, but the Grain-128AEAD specification for NIST uses little * order, but the Grain-128AEAD specification for NIST uses little
...@@ -187,26 +212,33 @@ void grain128_setup ...@@ -187,26 +212,33 @@ void grain128_setup
* P = [7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 * 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] * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24]
*/ */
#if defined(GRAIN128_ASM_HELPERS)
#define SWAP_BITS(out, in) \ #define SWAP_BITS(out, in) \
do { \ do { \
uint32_t tmp = (in); \ (out) = grain128_swap_word32((in)); \
} while (0)
#else
#define SWAP_BITS(out, in) \
do { \
uint32_t tmp = be_load_word32((in)); \
bit_permute_step_simple(tmp, 0x55555555, 1); \ bit_permute_step_simple(tmp, 0x55555555, 1); \
bit_permute_step_simple(tmp, 0x33333333, 2); \ bit_permute_step_simple(tmp, 0x33333333, 2); \
bit_permute_step_simple(tmp, 0x0f0f0f0f, 4); \ bit_permute_step_simple(tmp, 0x0f0f0f0f, 4); \
(out) = tmp; \ (out) = tmp; \
} while (0) } while (0)
#endif
/* Initialize the LFSR state with the nonce and padding */ /* Initialize the LFSR state with the nonce and padding */
SWAP_BITS(state->lfsr[0], be_load_word32(nonce)); SWAP_BITS(state->lfsr[0], nonce);
SWAP_BITS(state->lfsr[1], be_load_word32(nonce + 4)); SWAP_BITS(state->lfsr[1], nonce + 4);
SWAP_BITS(state->lfsr[2], be_load_word32(nonce + 8)); SWAP_BITS(state->lfsr[2], nonce + 8);
state->lfsr[3] = 0xFFFFFFFEU; /* pad with all-1s and a terminating 0 */ state->lfsr[3] = 0xFFFFFFFEU; /* pad with all-1s and a terminating 0 */
/* Initialize the NFSR state with the key */ /* Initialize the NFSR state with the key */
SWAP_BITS(k[0], be_load_word32(key)); SWAP_BITS(k[0], key);
SWAP_BITS(k[1], be_load_word32(key + 4)); SWAP_BITS(k[1], key + 4);
SWAP_BITS(k[2], be_load_word32(key + 8)); SWAP_BITS(k[2], key + 8);
SWAP_BITS(k[3], be_load_word32(key + 12)); SWAP_BITS(k[3], key + 12);
state->nfsr[0] = k[0]; state->nfsr[0] = k[0];
state->nfsr[1] = k[1]; state->nfsr[1] = k[1];
state->nfsr[2] = k[2]; state->nfsr[2] = k[2];
...@@ -215,7 +247,7 @@ void grain128_setup ...@@ -215,7 +247,7 @@ void grain128_setup
/* Perform 256 rounds of Grain-128 to mix up the initial state. /* Perform 256 rounds of Grain-128 to mix up the initial state.
* The rounds can be performed 32 at a time: 32 * 8 = 256 */ * The rounds can be performed 32 at a time: 32 * 8 = 256 */
for (round = 0; round < 8; ++round) { for (round = 0; round < 8; ++round) {
uint32_t y = grain128_preoutput(state); uint32_t y = grain128_preoutput_setup(state);
grain128_core(state, y, y); grain128_core(state, y, y);
} }
...@@ -241,6 +273,7 @@ void grain128_setup ...@@ -241,6 +273,7 @@ void grain128_setup
*/ */
static void grain128_next_keystream(grain128_state_t *state) static void grain128_next_keystream(grain128_state_t *state)
{ {
#if !defined(GRAIN128_ASM_HELPERS)
unsigned posn; unsigned posn;
for (posn = 0; posn < sizeof(state->ks); posn += 4) { for (posn = 0; posn < sizeof(state->ks); posn += 4) {
/* Get the next word of pre-output and run the Grain-128 core */ /* Get the next word of pre-output and run the Grain-128 core */
...@@ -264,6 +297,16 @@ static void grain128_next_keystream(grain128_state_t *state) ...@@ -264,6 +297,16 @@ static void grain128_next_keystream(grain128_state_t *state)
bit_permute_step_simple(x, 0x00ff00ff, 8); bit_permute_step_simple(x, 0x00ff00ff, 8);
be_store_word32(state->ks + posn, x); be_store_word32(state->ks + posn, x);
} }
#else
/* Generate the data and then perform the interleaving */
unsigned posn;
for (posn = 0; posn < sizeof(state->ks); posn += 4) {
uint32_t x = grain128_preoutput(state);
le_store_word32(state->ks + posn, x);
grain128_core(state, 0, 0);
}
grain128_interleave(state->ks);
#endif
} }
void grain128_authenticate void grain128_authenticate
...@@ -394,6 +437,8 @@ void grain128_decrypt ...@@ -394,6 +437,8 @@ void grain128_decrypt
state->posn = posn; state->posn = posn;
} }
#if !defined(__AVR__)
void grain128_compute_tag(grain128_state_t *state) void grain128_compute_tag(grain128_state_t *state)
{ {
uint64_t x; uint64_t x;
...@@ -409,3 +454,5 @@ void grain128_compute_tag(grain128_state_t *state) ...@@ -409,3 +454,5 @@ void grain128_compute_tag(grain128_state_t *state)
bit_permute_step_simple(x, 0x0f0f0f0f0f0f0f0fULL, 4); bit_permute_step_simple(x, 0x0f0f0f0f0f0f0f0fULL, 4);
be_store_word64(state->ks, x); be_store_word64(state->ks, x);
} }
#endif /* !__AVR__ */
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
/** /**
* \file internal-grain128.h * \file internal-grain128.h
* \brief Internal implementation of the Grain-128 stream cipher. * \brief Internal implementation of the Grain-128 stream cipher.
*
* References: https://grain-128aead.github.io/
*/ */
#ifdef __cplusplus #ifdef __cplusplus
...@@ -52,6 +54,25 @@ typedef struct ...@@ -52,6 +54,25 @@ typedef struct
} grain128_state_t; } grain128_state_t;
/** /**
* \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.
*/
void grain128_core
(grain128_state_t *state, uint32_t x, uint32_t x2);
/**
* \brief Generates 32 bits of pre-output data.
*
* \param state Grain-128 state.
*
* \return The generated 32 bits of pre-output data.
*/
uint32_t grain128_preoutput(const grain128_state_t *state);
/**
* \brief Sets up the initial Grain-128 state with the key and nonce. * \brief Sets up the initial Grain-128 state with the key and nonce.
* *
* \param state Grain-128 state to be initialized. * \param state Grain-128 state to be initialized.
......
...@@ -9,7 +9,7 @@ int crypto_aead_encrypt ...@@ -9,7 +9,7 @@ int crypto_aead_encrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return hyena_aead_encrypt return hyena_v1_aead_encrypt
(c, clen, m, mlen, ad, adlen, nsec, npub, k); (c, clen, m, mlen, ad, adlen, nsec, npub, k);
} }
...@@ -21,6 +21,6 @@ int crypto_aead_decrypt ...@@ -21,6 +21,6 @@ int crypto_aead_decrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return hyena_aead_decrypt return hyena_v1_aead_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k); (m, mlen, nsec, c, clen, ad, adlen, npub, k);
} }
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
* GIFT-128 block cipher. The algorithm has a 128-bit key, a 96-bit nonce, * GIFT-128 block cipher. The algorithm has a 128-bit key, a 96-bit nonce,
* and a 128-bit authentication tag. * and a 128-bit authentication tag.
* *
* This library implements both the v1 and v2 versions of HYENA from the
* authors. The v1 version was submitted to the second round of the
* NIST Lightweight Cryptography Competition but was later found to have a
* forgery attack. The authors fixed this with v2 but it was too late to
* submit the update for the second round.
*
* References: https://www.isical.ac.in/~lightweight/hyena/ * References: https://www.isical.ac.in/~lightweight/hyena/
*/ */
...@@ -56,12 +62,76 @@ extern "C" { ...@@ -56,12 +62,76 @@ extern "C" {
#define HYENA_NONCE_SIZE 12 #define HYENA_NONCE_SIZE 12
/** /**
* \brief Meta-information block for the HYENA cipher. * \brief Meta-information block for the HYENA-v1 cipher.
*/
extern aead_cipher_t const hyena_v1_cipher;
/**
* \brief Meta-information block for the HYENA-v2 cipher.
*/
extern aead_cipher_t const hyena_v2_cipher;
/**
* \brief Encrypts and authenticates a packet with HYENA-v1.
*
* \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()
*/ */
extern aead_cipher_t const hyena_cipher; int hyena_v1_aead_encrypt
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *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-v1.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \param nsec Secret nonce - not used by this algorithm.
* \param c Buffer 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_v1_aead_decrypt
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
const 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 HYENA. * \brief Encrypts and authenticates a packet with HYENA-v2.
* *
* \param c Buffer to receive the output. * \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes * \param clen On exit, set to the length of the output which includes
...@@ -81,7 +151,7 @@ extern aead_cipher_t const hyena_cipher; ...@@ -81,7 +151,7 @@ extern aead_cipher_t const hyena_cipher;
* *
* \sa hyena_aead_decrypt() * \sa hyena_aead_decrypt()
*/ */
int hyena_aead_encrypt int hyena_v2_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen, const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen, const unsigned char *ad, unsigned long long adlen,
...@@ -90,7 +160,7 @@ int hyena_aead_encrypt ...@@ -90,7 +160,7 @@ int hyena_aead_encrypt
const unsigned char *k); const unsigned char *k);
/** /**
* \brief Decrypts and authenticates a packet with HYENA. * \brief Decrypts and authenticates a packet with HYENA-v2.
* *
* \param m Buffer to receive the plaintext message on output. * \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output. * \param mlen Receives the length of the plaintext message on output.
...@@ -111,7 +181,7 @@ int hyena_aead_encrypt ...@@ -111,7 +181,7 @@ int hyena_aead_encrypt
* *
* \sa hyena_aead_encrypt() * \sa hyena_aead_encrypt()
*/ */
int hyena_aead_decrypt int hyena_v2_aead_decrypt
(unsigned char *m, unsigned long long *mlen, (unsigned char *m, unsigned long long *mlen,
unsigned char *nsec, unsigned char *nsec,
const unsigned char *c, unsigned long long clen, const unsigned char *c, unsigned long long clen,
......
...@@ -47,11 +47,13 @@ ...@@ -47,11 +47,13 @@
* in any of the NIST submissions so we don't bother with it in this library. * in any of the NIST submissions so we don't bother with it in this library.
* *
* References: https://eprint.iacr.org/2017/622.pdf, * References: https://eprint.iacr.org/2017/622.pdf,
* https://eprint.iacr.org/2020/412.pdf,
* https://giftcipher.github.io/gift/ * https://giftcipher.github.io/gift/
*/ */
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "internal-gift128-config.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -63,16 +65,23 @@ extern "C" { ...@@ -63,16 +65,23 @@ extern "C" {
#define GIFT128_BLOCK_SIZE 16 #define GIFT128_BLOCK_SIZE 16
/** /**
* \brief Number of round keys for the fixsliced representation of GIFT-128. * \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 #define GIFT128_ROUND_KEYS 80
#endif
/** /**
* \brief Structure of the key schedule for GIFT-128 (bit-sliced). * \brief Structure of the key schedule for GIFT-128 (bit-sliced).
*/ */
typedef struct typedef struct
{ {
/** Pre-computed round keys in the fixsliced form */ /** Pre-computed round keys for bit-sliced GIFT-128 */
uint32_t k[GIFT128_ROUND_KEYS]; uint32_t k[GIFT128_ROUND_KEYS];
} gift128b_key_schedule_t; } gift128b_key_schedule_t;
...@@ -81,14 +90,9 @@ typedef struct ...@@ -81,14 +90,9 @@ typedef struct
* \brief Initializes the key schedule for GIFT-128 (bit-sliced). * \brief Initializes the key schedule for GIFT-128 (bit-sliced).
* *
* \param ks Points to the key schedule to initialize. * \param ks Points to the key schedule to initialize.
* \param key Points to the key data. * \param key Points to the 16 bytes of 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 void gift128b_init(gift128b_key_schedule_t *ks, const unsigned char *key);
(gift128b_key_schedule_t *ks, const unsigned char *key, size_t key_len);
/** /**
* \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced). * \brief Encrypts a 128-bit block with GIFT-128 (bit-sliced).
...@@ -145,14 +149,9 @@ typedef gift128b_key_schedule_t gift128n_key_schedule_t; ...@@ -145,14 +149,9 @@ typedef gift128b_key_schedule_t gift128n_key_schedule_t;
* \brief Initializes the key schedule for GIFT-128 (nibble-based). * \brief Initializes the key schedule for GIFT-128 (nibble-based).
* *
* \param ks Points to the key schedule to initialize. * \param ks Points to the key schedule to initialize.
* \param key Points to the key data. * \param key Points to the 16 bytes of 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 void gift128n_init(gift128n_key_schedule_t *ks, const unsigned char *key);
(gift128n_key_schedule_t *ks, const unsigned char *key, size_t key_len);
/** /**
* \brief Encrypts a 128-bit block with GIFT-128 (nibble-based). * \brief Encrypts a 128-bit block with GIFT-128 (nibble-based).
...@@ -182,13 +181,31 @@ void gift128n_decrypt ...@@ -182,13 +181,31 @@ void gift128n_decrypt
(const gift128n_key_schedule_t *ks, unsigned char *output, (const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input); 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). * \brief Encrypts a 128-bit block with TweGIFT-128 (tweakable variant).
* *
* \param ks Points to the GIFT-128 key schedule. * \param ks Points to the GIFT-128 key schedule.
* \param output Output buffer which must be at least 16 bytes in length. * \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 input Input buffer which must be at least 16 bytes in length.
* \param tweak 4-bit tweak value. * \param tweak 4-bit tweak value expanded to 32-bit.
* *
* The \a input and \a output buffers can be the same buffer for * The \a input and \a output buffers can be the same buffer for
* in-place encryption. * in-place encryption.
...@@ -200,7 +217,7 @@ void gift128n_decrypt ...@@ -200,7 +217,7 @@ void gift128n_decrypt
*/ */
void gift128t_encrypt void gift128t_encrypt
(const gift128n_key_schedule_t *ks, unsigned char *output, (const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned char tweak); const unsigned char *input, uint32_t tweak);
/** /**
* \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant). * \brief Decrypts a 128-bit block with TweGIFT-128 (tweakable variant).
...@@ -208,7 +225,7 @@ void gift128t_encrypt ...@@ -208,7 +225,7 @@ void gift128t_encrypt
* \param ks Points to the GIFT-128 key schedule. * \param ks Points to the GIFT-128 key schedule.
* \param output Output buffer which must be at least 16 bytes in length. * \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 input Input buffer which must be at least 16 bytes in length.
* \param tweak 4-bit tweak value. * \param tweak 4-bit tweak value expanded to 32-bit.
* *
* The \a input and \a output buffers can be the same buffer for * The \a input and \a output buffers can be the same buffer for
* in-place encryption. * in-place encryption.
...@@ -220,7 +237,7 @@ void gift128t_encrypt ...@@ -220,7 +237,7 @@ void gift128t_encrypt
*/ */
void gift128t_decrypt void gift128t_decrypt
(const gift128n_key_schedule_t *ks, unsigned char *output, (const gift128n_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned char tweak); const unsigned char *input, uint32_t tweak);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -238,6 +238,17 @@ ...@@ -238,6 +238,17 @@
} \ } \
} while (0) } 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 */ /* Rotation macros for 32-bit arguments */
/* Generic left rotate */ /* Generic left rotate */
...@@ -254,6 +265,8 @@ ...@@ -254,6 +265,8 @@
(_temp >> (bits)) | (_temp << (32 - (bits))); \ (_temp >> (bits)) | (_temp << (32 - (bits))); \
})) }))
#if !LW_CRYPTO_ROTATE32_COMPOSED
/* Left rotate by a specific number of bits. These macros may be replaced /* Left rotate by a specific number of bits. These macros may be replaced
* with more efficient ones on platforms that lack a barrel shifter */ * with more efficient ones on platforms that lack a barrel shifter */
#define leftRotate1(a) (leftRotate((a), 1)) #define leftRotate1(a) (leftRotate((a), 1))
...@@ -322,6 +335,138 @@ ...@@ -322,6 +335,138 @@
#define rightRotate30(a) (rightRotate((a), 30)) #define rightRotate30(a) (rightRotate((a), 30))
#define rightRotate31(a) (rightRotate((a), 31)) #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 */ /* Rotation macros for 64-bit arguments */
/* Generic left rotate */ /* Generic left rotate */
......
...@@ -9,7 +9,7 @@ int crypto_aead_encrypt ...@@ -9,7 +9,7 @@ int crypto_aead_encrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return hyena_aead_encrypt return hyena_v2_aead_encrypt
(c, clen, m, mlen, ad, adlen, nsec, npub, k); (c, clen, m, mlen, ad, adlen, nsec, npub, k);
} }
...@@ -21,6 +21,6 @@ int crypto_aead_decrypt ...@@ -21,6 +21,6 @@ int crypto_aead_decrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return hyena_aead_decrypt return hyena_v2_aead_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k); (m, mlen, nsec, c, clen, ad, adlen, npub, k);
} }
...@@ -25,14 +25,24 @@ ...@@ -25,14 +25,24 @@
#include "internal-util.h" #include "internal-util.h"
#include <string.h> #include <string.h>
aead_cipher_t const hyena_cipher = { aead_cipher_t const hyena_v1_cipher = {
"HYENA", "HYENA-v1",
HYENA_KEY_SIZE, HYENA_KEY_SIZE,
HYENA_NONCE_SIZE, HYENA_NONCE_SIZE,
HYENA_TAG_SIZE, HYENA_TAG_SIZE,
AEAD_FLAG_LITTLE_ENDIAN, AEAD_FLAG_LITTLE_ENDIAN,
hyena_aead_encrypt, hyena_v1_aead_encrypt,
hyena_aead_decrypt hyena_v1_aead_decrypt
};
aead_cipher_t const hyena_v2_cipher = {
"HYENA-v2",
HYENA_KEY_SIZE,
HYENA_NONCE_SIZE,
HYENA_TAG_SIZE,
AEAD_FLAG_LITTLE_ENDIAN,
hyena_v2_aead_encrypt,
hyena_v2_aead_decrypt
}; };
/** /**
...@@ -69,7 +79,236 @@ static void hyena_triple_delta(unsigned char D[8]) ...@@ -69,7 +79,236 @@ static void hyena_triple_delta(unsigned char D[8])
} }
/** /**
* \brief Process the associated data for HYENA. * \brief Process the associated data for HYENA-v1.
*
* \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_v1_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_v1_aead_encrypt
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, 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_v1_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_v1_aead_decrypt
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
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_v1_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);
}
/**
* \brief Process the associated data for HYENA-v2.
* *
* \param ks Key schedule for the GIFT-128 cipher. * \param ks Key schedule for the GIFT-128 cipher.
* \param Y Internal hash state of HYENA. * \param Y Internal hash state of HYENA.
...@@ -77,7 +316,7 @@ static void hyena_triple_delta(unsigned char D[8]) ...@@ -77,7 +316,7 @@ static void hyena_triple_delta(unsigned char D[8])
* \param ad Points to the associated data. * \param ad Points to the associated data.
* \param adlen Length of the associated data in bytes. * \param adlen Length of the associated data in bytes.
*/ */
static void hyena_process_ad static void hyena_v2_process_ad
(const gift128n_key_schedule_t *ks, unsigned char Y[16], (const gift128n_key_schedule_t *ks, unsigned char Y[16],
unsigned char D[8], const unsigned char *ad, unsigned char D[8], const unsigned char *ad,
unsigned long long adlen) unsigned long long adlen)
...@@ -113,7 +352,7 @@ static void hyena_process_ad ...@@ -113,7 +352,7 @@ static void hyena_process_ad
} }
} }
int hyena_aead_encrypt int hyena_v2_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen, const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen, const unsigned char *ad, unsigned long long adlen,
...@@ -146,7 +385,7 @@ int hyena_aead_encrypt ...@@ -146,7 +385,7 @@ int hyena_aead_encrypt
memcpy(D, Y + 8, 8); memcpy(D, Y + 8, 8);
/* Process the associated data */ /* Process the associated data */
hyena_process_ad(&ks, Y, D, ad, adlen); hyena_v2_process_ad(&ks, Y, D, ad, adlen);
/* Encrypt the plaintext to produce the ciphertext */ /* Encrypt the plaintext to produce the ciphertext */
if (mlen > 0) { if (mlen > 0) {
...@@ -198,7 +437,7 @@ int hyena_aead_encrypt ...@@ -198,7 +437,7 @@ int hyena_aead_encrypt
return 0; return 0;
} }
int hyena_aead_decrypt int hyena_v2_aead_decrypt
(unsigned char *m, unsigned long long *mlen, (unsigned char *m, unsigned long long *mlen,
unsigned char *nsec, unsigned char *nsec,
const unsigned char *c, unsigned long long clen, const unsigned char *c, unsigned long long clen,
...@@ -234,7 +473,7 @@ int hyena_aead_decrypt ...@@ -234,7 +473,7 @@ int hyena_aead_decrypt
memcpy(D, Y + 8, 8); memcpy(D, Y + 8, 8);
/* Process the associated data */ /* Process the associated data */
hyena_process_ad(&ks, Y, D, ad, adlen); hyena_v2_process_ad(&ks, Y, D, ad, adlen);
/* Decrypt the ciphertext to produce the plaintext */ /* Decrypt the ciphertext to produce the plaintext */
clen -= HYENA_TAG_SIZE; clen -= HYENA_TAG_SIZE;
......
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
* GIFT-128 block cipher. The algorithm has a 128-bit key, a 96-bit nonce, * GIFT-128 block cipher. The algorithm has a 128-bit key, a 96-bit nonce,
* and a 128-bit authentication tag. * and a 128-bit authentication tag.
* *
* This library implements both the v1 and v2 versions of HYENA from the
* authors. The v1 version was submitted to the second round of the
* NIST Lightweight Cryptography Competition but was later found to have a
* forgery attack. The authors fixed this with v2 but it was too late to
* submit the update for the second round.
*
* References: https://www.isical.ac.in/~lightweight/hyena/ * References: https://www.isical.ac.in/~lightweight/hyena/
*/ */
...@@ -56,12 +62,76 @@ extern "C" { ...@@ -56,12 +62,76 @@ extern "C" {
#define HYENA_NONCE_SIZE 12 #define HYENA_NONCE_SIZE 12
/** /**
* \brief Meta-information block for the HYENA cipher. * \brief Meta-information block for the HYENA-v1 cipher.
*/
extern aead_cipher_t const hyena_v1_cipher;
/**
* \brief Meta-information block for the HYENA-v2 cipher.
*/
extern aead_cipher_t const hyena_v2_cipher;
/**
* \brief Encrypts and authenticates a packet with HYENA-v1.
*
* \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()
*/ */
extern aead_cipher_t const hyena_cipher; int hyena_v1_aead_encrypt
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *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-v1.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \param nsec Secret nonce - not used by this algorithm.
* \param c Buffer 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_v1_aead_decrypt
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
const 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 HYENA. * \brief Encrypts and authenticates a packet with HYENA-v2.
* *
* \param c Buffer to receive the output. * \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes * \param clen On exit, set to the length of the output which includes
...@@ -81,7 +151,7 @@ extern aead_cipher_t const hyena_cipher; ...@@ -81,7 +151,7 @@ extern aead_cipher_t const hyena_cipher;
* *
* \sa hyena_aead_decrypt() * \sa hyena_aead_decrypt()
*/ */
int hyena_aead_encrypt int hyena_v2_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen, const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen, const unsigned char *ad, unsigned long long adlen,
...@@ -90,7 +160,7 @@ int hyena_aead_encrypt ...@@ -90,7 +160,7 @@ int hyena_aead_encrypt
const unsigned char *k); const unsigned char *k);
/** /**
* \brief Decrypts and authenticates a packet with HYENA. * \brief Decrypts and authenticates a packet with HYENA-v2.
* *
* \param m Buffer to receive the plaintext message on output. * \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output. * \param mlen Receives the length of the plaintext message on output.
...@@ -111,7 +181,7 @@ int hyena_aead_encrypt ...@@ -111,7 +181,7 @@ int hyena_aead_encrypt
* *
* \sa hyena_aead_encrypt() * \sa hyena_aead_encrypt()
*/ */
int hyena_aead_decrypt int hyena_v2_aead_decrypt
(unsigned char *m, unsigned long long *mlen, (unsigned char *m, unsigned long long *mlen,
unsigned char *nsec, unsigned char *nsec,
const unsigned char *c, unsigned long long clen, const unsigned char *c, unsigned long long clen,
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "internal-photon256.h" #include "internal-photon256.h"
#include "internal-util.h" #include "internal-util.h"
#if !defined(__AVR__)
/** /**
* \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form.
*/ */
...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) ...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE])
/* Convert back from bit-sliced form to regular form */ /* Convert back from bit-sliced form to regular form */
photon256_from_sliced(state, S.bytes); photon256_from_sliced(state, S.bytes);
} }
#endif /* !__AVR__ */
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "internal-photon256.h" #include "internal-photon256.h"
#include "internal-util.h" #include "internal-util.h"
#if !defined(__AVR__)
/** /**
* \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form.
*/ */
...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) ...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE])
/* Convert back from bit-sliced form to regular form */ /* Convert back from bit-sliced form to regular form */
photon256_from_sliced(state, S.bytes); photon256_from_sliced(state, S.bytes);
} }
#endif /* !__AVR__ */
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "internal-photon256.h" #include "internal-photon256.h"
#include "internal-util.h" #include "internal-util.h"
#if !defined(__AVR__)
/** /**
* \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form.
*/ */
...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) ...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE])
/* Convert back from bit-sliced form to regular form */ /* Convert back from bit-sliced form to regular form */
photon256_from_sliced(state, S.bytes); photon256_from_sliced(state, S.bytes);
} }
#endif /* !__AVR__ */
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "internal-photon256.h" #include "internal-photon256.h"
#include "internal-util.h" #include "internal-util.h"
#if !defined(__AVR__)
/** /**
* \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form.
*/ */
...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) ...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE])
/* Convert back from bit-sliced form to regular form */ /* Convert back from bit-sliced form to regular form */
photon256_from_sliced(state, S.bytes); photon256_from_sliced(state, S.bytes);
} }
#endif /* !__AVR__ */
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "internal-photon256.h" #include "internal-photon256.h"
#include "internal-util.h" #include "internal-util.h"
#if !defined(__AVR__)
/** /**
* \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form. * \brief Number of rounds in the PHOTON-256 permutation in bit-sliced form.
*/ */
...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE]) ...@@ -477,3 +479,5 @@ void photon256_permute(unsigned char state[PHOTON256_STATE_SIZE])
/* Convert back from bit-sliced form to regular form */ /* Convert back from bit-sliced form to regular form */
photon256_from_sliced(state, S.bytes); photon256_from_sliced(state, S.bytes);
} }
#endif /* !__AVR__ */
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF 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_SATURNIN_H
#define LW_INTERNAL_SATURNIN_H
/**
* \file internal-saturnin.h
* \brief Saturnin block cipher.
*
* References: https://project.inria.fr/saturnin/
*/
#include "internal-util.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of a Saturnin block in bytes.
*/
#define SATURNIN_BLOCK_SIZE 32
/**
* \brief Domain separator index 1 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_1 0
/**
* \brief Domain separator index 2 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_2 10
/**
* \brief Domain separator index 3 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_3 20
/**
* \brief Domain separator index 4 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_4 30
/**
* \brief Domain separator index 5 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_5 40
/**
* \brief Domain separator index 6 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_6 50
/**
* \brief Domain separator index 7 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_7 60
/**
* \brief Domain separator index 8 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_8 76
/**
* \brief Structure of the key schedule for Saturnin.
*/
typedef struct
{
/** Pre-computed round keys for Saturnin */
uint32_t k[16];
} saturnin_key_schedule_t;
/**
* \brief Sets up a key schedule for Saturnin.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the 32 bytes of the key data.
*/
void saturnin_setup_key
(saturnin_key_schedule_t *ks, const unsigned char *key);
/**
* \brief Encrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void saturnin_encrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
/**
* \brief Decrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place decryption.
*/
void saturnin_decrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
#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_SATURNIN_H
#define LW_INTERNAL_SATURNIN_H
/**
* \file internal-saturnin.h
* \brief Saturnin block cipher.
*
* References: https://project.inria.fr/saturnin/
*/
#include "internal-util.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of a Saturnin block in bytes.
*/
#define SATURNIN_BLOCK_SIZE 32
/**
* \brief Domain separator index 1 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_1 0
/**
* \brief Domain separator index 2 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_2 10
/**
* \brief Domain separator index 3 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_3 20
/**
* \brief Domain separator index 4 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_4 30
/**
* \brief Domain separator index 5 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_5 40
/**
* \brief Domain separator index 6 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_6 50
/**
* \brief Domain separator index 7 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_7 60
/**
* \brief Domain separator index 8 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_8 76
/**
* \brief Structure of the key schedule for Saturnin.
*/
typedef struct
{
/** Pre-computed round keys for Saturnin */
uint32_t k[16];
} saturnin_key_schedule_t;
/**
* \brief Sets up a key schedule for Saturnin.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the 32 bytes of the key data.
*/
void saturnin_setup_key
(saturnin_key_schedule_t *ks, const unsigned char *key);
/**
* \brief Encrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void saturnin_encrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
/**
* \brief Decrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place decryption.
*/
void saturnin_decrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
#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_SATURNIN_H
#define LW_INTERNAL_SATURNIN_H
/**
* \file internal-saturnin.h
* \brief Saturnin block cipher.
*
* References: https://project.inria.fr/saturnin/
*/
#include "internal-util.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of a Saturnin block in bytes.
*/
#define SATURNIN_BLOCK_SIZE 32
/**
* \brief Domain separator index 1 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_1 0
/**
* \brief Domain separator index 2 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_2 10
/**
* \brief Domain separator index 3 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_3 20
/**
* \brief Domain separator index 4 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_4 30
/**
* \brief Domain separator index 5 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_5 40
/**
* \brief Domain separator index 6 for the 10-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_10_6 50
/**
* \brief Domain separator index 7 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_7 60
/**
* \brief Domain separator index 8 for the 16-round version of Saturnin.
*/
#define SATURNIN_DOMAIN_16_8 76
/**
* \brief Structure of the key schedule for Saturnin.
*/
typedef struct
{
/** Pre-computed round keys for Saturnin */
uint32_t k[16];
} saturnin_key_schedule_t;
/**
* \brief Sets up a key schedule for Saturnin.
*
* \param ks Points to the key schedule to initialize.
* \param key Points to the 32 bytes of the key data.
*/
void saturnin_setup_key
(saturnin_key_schedule_t *ks, const unsigned char *key);
/**
* \brief Encrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place encryption.
*/
void saturnin_encrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
/**
* \brief Decrypts a 256-bit block with Saturnin.
*
* \param ks Points to the Saturnin key schedule.
* \param output Output buffer which must be at least 32 bytes in length.
* \param input Input buffer which must be at least 32 bytes in length.
* \param domain Domain separator and round count indicator.
*
* The \a input and \a output buffers can be the same buffer for
* in-place decryption.
*/
void saturnin_decrypt_block
(const saturnin_key_schedule_t *ks, unsigned char *output,
const unsigned char *input, unsigned domain);
#ifdef __cplusplus
}
#endif
#endif
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -74,6 +74,21 @@ extern "C" { ...@@ -74,6 +74,21 @@ extern "C" {
( row3 & 0x00FF0000U); \ ( row3 & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_permute_tk_half(tk2, tk3) \
do { \
/* Permute the bottom half of the tweakey state in place, no swap */ \
uint32_t row2 = tk2; \
uint32_t row3 = tk3; \
row3 = (row3 << 16) | (row3 >> 16); \
tk2 = ((row2 >> 8) & 0x000000FFU) | \
((row2 << 16) & 0x00FF0000U) | \
( row3 & 0xFF00FF00U); \
tk3 = ((row2 >> 16) & 0x000000FFU) | \
(row2 & 0xFF000000U) | \
((row3 << 8) & 0x0000FF00U) | \
( row3 & 0x00FF0000U); \
} while (0)
#define skinny128_inv_permute_tk(tk) \ #define skinny128_inv_permute_tk(tk) \
do { \ do { \
/* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \ /* PT' = [8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 4, 7, 6, 3, 5, 1] */ \
...@@ -91,6 +106,21 @@ extern "C" { ...@@ -91,6 +106,21 @@ extern "C" {
((row1 << 8) & 0x00FF0000U); \ ((row1 << 8) & 0x00FF0000U); \
} while (0) } while (0)
#define skinny128_inv_permute_tk_half(tk0, tk1) \
do { \
/* Permute the top half of the tweakey state in place, no swap */ \
uint32_t row0 = tk0; \
uint32_t row1 = tk1; \
tk0 = ((row0 >> 16) & 0x000000FFU) | \
((row0 << 8) & 0x0000FF00U) | \
((row1 << 16) & 0x00FF0000U) | \
( row1 & 0xFF000000U); \
tk1 = ((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 * Apply the SKINNY sbox. The original version from the specification is
* equivalent to: * equivalent to:
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "internal-spook.h" #include "internal-spook.h"
#if !defined(__AVR__)
/** /**
* \brief Number of steps in the Clyde-128 block cipher. * \brief Number of steps in the Clyde-128 block cipher.
* *
...@@ -43,9 +45,9 @@ static uint8_t const rc[CLYDE128_STEPS][8] = { ...@@ -43,9 +45,9 @@ static uint8_t const rc[CLYDE128_STEPS][8] = {
}; };
void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) const uint32_t input[CLYDE128_BLOCK_SIZE / 4],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4])
{ {
uint32_t k0, k1, k2, k3; uint32_t k0, k1, k2, k3;
uint32_t t0, t1, t2, t3; uint32_t t0, t1, t2, t3;
...@@ -154,9 +156,9 @@ void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], ...@@ -154,9 +156,9 @@ void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE],
} }
void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const unsigned char input[CLYDE128_BLOCK_SIZE]) const unsigned char input[CLYDE128_BLOCK_SIZE],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4])
{ {
uint32_t k0, k1, k2, k3; uint32_t k0, k1, k2, k3;
uint32_t t0, t1, t2, t3; uint32_t t0, t1, t2, t3;
...@@ -555,3 +557,5 @@ void shadow384(shadow384_state_t *state) ...@@ -555,3 +557,5 @@ void shadow384(shadow384_state_t *state)
le_store_word32(state->B + 44, s23); le_store_word32(state->B + 44, s23);
#endif #endif
} }
#endif /* !__AVR__ */
...@@ -93,31 +93,31 @@ typedef union ...@@ -93,31 +93,31 @@ typedef union
* \brief Encrypts a block with the Clyde-128 block cipher. * \brief Encrypts a block with the Clyde-128 block cipher.
* *
* \param key Points to the key to encrypt with. * \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 output Output buffer for the ciphertext.
* \param input Input buffer for the plaintext. * \param input Input buffer for the plaintext.
* \param tweak Points to the tweak to encrypt with.
* *
* \sa clyde128_decrypt() * \sa clyde128_decrypt()
*/ */
void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); const uint32_t input[CLYDE128_BLOCK_SIZE / 4],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4]);
/** /**
* \brief Decrypts a block with the Clyde-128 block cipher. * \brief Decrypts a block with the Clyde-128 block cipher.
* *
* \param key Points to the key to decrypt with. * \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 output Output buffer for the plaintext.
* \param input Input buffer for the ciphertext. * \param input Input buffer for the ciphertext.
* \param tweak Points to the tweak to decrypt with.
* *
* \sa clyde128_encrypt() * \sa clyde128_encrypt()
*/ */
void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const unsigned char input[CLYDE128_BLOCK_SIZE]); const unsigned char input[CLYDE128_BLOCK_SIZE],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4]);
/** /**
* \brief Performs the Shadow-512 permutation on a state. * \brief Performs the Shadow-512 permutation on a state.
......
...@@ -86,7 +86,7 @@ static void spook_128_512_init ...@@ -86,7 +86,7 @@ static void spook_128_512_init
state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40;
} }
memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE);
clyde128_encrypt(k, state->W, state->W + 12, state->W + 4); clyde128_encrypt(k, state->W + 12, state->W + 4, state->W);
shadow512(state); shadow512(state);
} }
...@@ -111,7 +111,7 @@ static void spook_128_384_init ...@@ -111,7 +111,7 @@ static void spook_128_384_init
state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40; state->B[CLYDE128_BLOCK_SIZE - 1] |= 0x40;
} }
memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE); memcpy(state->B + CLYDE128_BLOCK_SIZE, npub, CLYDE128_BLOCK_SIZE);
clyde128_encrypt(k, state->W, state->W + 8, state->W + 4); clyde128_encrypt(k, state->W + 8, state->W + 4, state->W);
shadow384(state); shadow384(state);
} }
...@@ -310,7 +310,7 @@ int spook_128_512_su_aead_encrypt ...@@ -310,7 +310,7 @@ int spook_128_512_su_aead_encrypt
/* Compute the authentication tag */ /* Compute the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_encrypt(k, state.W + 4, state.W, state.W); clyde128_encrypt(k, state.W, state.W, state.W + 4);
memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); memcpy(c + mlen, state.B, SPOOK_TAG_SIZE);
return 0; return 0;
} }
...@@ -345,7 +345,7 @@ int spook_128_512_su_aead_decrypt ...@@ -345,7 +345,7 @@ int spook_128_512_su_aead_decrypt
/* Check the authentication tag */ /* Check the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); clyde128_decrypt(k, state.W + 4, c + clen, state.W + 4);
return aead_check_tag return aead_check_tag
(m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE);
} }
...@@ -377,7 +377,7 @@ int spook_128_384_su_aead_encrypt ...@@ -377,7 +377,7 @@ int spook_128_384_su_aead_encrypt
/* Compute the authentication tag */ /* Compute the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_encrypt(k, state.W + 4, state.W, state.W); clyde128_encrypt(k, state.W, state.W, state.W + 4);
memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); memcpy(c + mlen, state.B, SPOOK_TAG_SIZE);
return 0; return 0;
} }
...@@ -412,7 +412,7 @@ int spook_128_384_su_aead_decrypt ...@@ -412,7 +412,7 @@ int spook_128_384_su_aead_decrypt
/* Check the authentication tag */ /* Check the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); clyde128_decrypt(k, state.W + 4, c + clen, state.W + 4);
return aead_check_tag return aead_check_tag
(m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE);
} }
...@@ -444,7 +444,7 @@ int spook_128_512_mu_aead_encrypt ...@@ -444,7 +444,7 @@ int spook_128_512_mu_aead_encrypt
/* Compute the authentication tag */ /* Compute the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_encrypt(k, state.W + 4, state.W, state.W); clyde128_encrypt(k, state.W, state.W, state.W + 4);
memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); memcpy(c + mlen, state.B, SPOOK_TAG_SIZE);
return 0; return 0;
} }
...@@ -479,7 +479,7 @@ int spook_128_512_mu_aead_decrypt ...@@ -479,7 +479,7 @@ int spook_128_512_mu_aead_decrypt
/* Check the authentication tag */ /* Check the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); clyde128_decrypt(k, state.W + 4, c + clen, state.W + 4);
return aead_check_tag return aead_check_tag
(m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE);
} }
...@@ -511,7 +511,7 @@ int spook_128_384_mu_aead_encrypt ...@@ -511,7 +511,7 @@ int spook_128_384_mu_aead_encrypt
/* Compute the authentication tag */ /* Compute the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_encrypt(k, state.W + 4, state.W, state.W); clyde128_encrypt(k, state.W, state.W, state.W + 4);
memcpy(c + mlen, state.B, SPOOK_TAG_SIZE); memcpy(c + mlen, state.B, SPOOK_TAG_SIZE);
return 0; return 0;
} }
...@@ -546,7 +546,7 @@ int spook_128_384_mu_aead_decrypt ...@@ -546,7 +546,7 @@ int spook_128_384_mu_aead_decrypt
/* Check the authentication tag */ /* Check the authentication tag */
state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80; state.B[CLYDE128_BLOCK_SIZE * 2 - 1] |= 0x80;
clyde128_decrypt(k, state.W + 4, state.W + 4, c + clen); clyde128_decrypt(k, state.W + 4, c + clen, state.W + 4);
return aead_check_tag return aead_check_tag
(m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE); (m, clen, state.B, state.B + CLYDE128_BLOCK_SIZE, SPOOK_TAG_SIZE);
} }
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "internal-spook.h" #include "internal-spook.h"
#if !defined(__AVR__)
/** /**
* \brief Number of steps in the Clyde-128 block cipher. * \brief Number of steps in the Clyde-128 block cipher.
* *
...@@ -43,9 +45,9 @@ static uint8_t const rc[CLYDE128_STEPS][8] = { ...@@ -43,9 +45,9 @@ static uint8_t const rc[CLYDE128_STEPS][8] = {
}; };
void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const uint32_t input[CLYDE128_BLOCK_SIZE / 4]) const uint32_t input[CLYDE128_BLOCK_SIZE / 4],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4])
{ {
uint32_t k0, k1, k2, k3; uint32_t k0, k1, k2, k3;
uint32_t t0, t1, t2, t3; uint32_t t0, t1, t2, t3;
...@@ -154,9 +156,9 @@ void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], ...@@ -154,9 +156,9 @@ void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE],
} }
void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const unsigned char input[CLYDE128_BLOCK_SIZE]) const unsigned char input[CLYDE128_BLOCK_SIZE],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4])
{ {
uint32_t k0, k1, k2, k3; uint32_t k0, k1, k2, k3;
uint32_t t0, t1, t2, t3; uint32_t t0, t1, t2, t3;
...@@ -555,3 +557,5 @@ void shadow384(shadow384_state_t *state) ...@@ -555,3 +557,5 @@ void shadow384(shadow384_state_t *state)
le_store_word32(state->B + 44, s23); le_store_word32(state->B + 44, s23);
#endif #endif
} }
#endif /* !__AVR__ */
...@@ -93,31 +93,31 @@ typedef union ...@@ -93,31 +93,31 @@ typedef union
* \brief Encrypts a block with the Clyde-128 block cipher. * \brief Encrypts a block with the Clyde-128 block cipher.
* *
* \param key Points to the key to encrypt with. * \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 output Output buffer for the ciphertext.
* \param input Input buffer for the plaintext. * \param input Input buffer for the plaintext.
* \param tweak Points to the tweak to encrypt with.
* *
* \sa clyde128_decrypt() * \sa clyde128_decrypt()
*/ */
void clyde128_encrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const uint32_t input[CLYDE128_BLOCK_SIZE / 4]); const uint32_t input[CLYDE128_BLOCK_SIZE / 4],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4]);
/** /**
* \brief Decrypts a block with the Clyde-128 block cipher. * \brief Decrypts a block with the Clyde-128 block cipher.
* *
* \param key Points to the key to decrypt with. * \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 output Output buffer for the plaintext.
* \param input Input buffer for the ciphertext. * \param input Input buffer for the ciphertext.
* \param tweak Points to the tweak to decrypt with.
* *
* \sa clyde128_encrypt() * \sa clyde128_encrypt()
*/ */
void clyde128_decrypt(const unsigned char key[CLYDE128_KEY_SIZE], 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], uint32_t output[CLYDE128_BLOCK_SIZE / 4],
const unsigned char input[CLYDE128_BLOCK_SIZE]); const unsigned char input[CLYDE128_BLOCK_SIZE],
const uint32_t tweak[CLYDE128_TWEAK_SIZE / 4]);
/** /**
* \brief Performs the Shadow-512 permutation on a state. * \brief Performs the Shadow-512 permutation on a state.
......
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