From 22eafbcaf6635dc5e1f8a734b1f7c5ab84b5a5ea Mon Sep 17 00:00:00 2001 From: Roman Oliynykov Date: Wed, 15 Jul 2015 19:30:00 +0300 Subject: [PATCH] Adding reference implementation --- kalyna.c | 473 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ kalyna.h | 87 ++++++++++ main.c | 326 +++++++++++++++++++++++++++++++++++++ makefile | 4 + tables.c | 183 +++++++++++++++++++++ tables.h | 21 +++ transformations.h | 324 +++++++++++++++++++++++++++++++++++++ 7 files changed, 1418 insertions(+) create mode 100644 kalyna.c create mode 100644 kalyna.h create mode 100644 main.c create mode 100644 makefile create mode 100644 tables.c create mode 100644 tables.h create mode 100644 transformations.h diff --git a/kalyna.c b/kalyna.c new file mode 100644 index 0000000..d0a8bb6 --- /dev/null +++ b/kalyna.c @@ -0,0 +1,473 @@ +/* + +Reference implementation of the Kalyna block cipher (DSTU 7624:2014), all block and key length variants + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#include "transformations.h" +#include "tables.h" + + +kalyna_t* KalynaInit(size_t block_size, size_t key_size) { + int i; + kalyna_t* ctx = (kalyna_t*)malloc(sizeof(kalyna_t)); + + if (block_size == kBLOCK_128) { + ctx->nb = kBLOCK_128 / kBITS_IN_WORD; + if (key_size == kKEY_128) { + ctx->nk = kKEY_128 / kBITS_IN_WORD; + ctx->nr = kNR_128; + } else if (key_size == kKEY_256){ + ctx->nk = kKEY_256 / kBITS_IN_WORD; + ctx->nr = kNR_256; + } else { + fprintf(stderr, "Error: unsupported key size.\n"); + return NULL; + } + } else if (block_size == 256) { + ctx->nb = kBLOCK_256 / kBITS_IN_WORD; + if (key_size == kKEY_256) { + ctx->nk = kKEY_256 / kBITS_IN_WORD; + ctx->nr = kNR_256; + } else if (key_size == kKEY_512){ + ctx->nk = kKEY_512 / kBITS_IN_WORD; + ctx->nr = kNR_512; + } else { + fprintf(stderr, "Error: unsupported key size.\n"); + return NULL; + } + } else if (block_size == kBLOCK_512) { + ctx->nb = kBLOCK_512 / kBITS_IN_WORD; + if (key_size == kKEY_512) { + ctx->nk = kKEY_512 / kBITS_IN_WORD; + ctx->nr = kNR_512; + } else { + fprintf(stderr, "Error: unsupported key size.\n"); + return NULL; + } + } else { + fprintf(stderr, "Error: unsupported block size.\n"); + return NULL; + } + + ctx->state = (uint64_t*)calloc(ctx->nb, sizeof(uint64_t)); + if (ctx->state == NULL) + perror("Could not allocate memory for cipher state."); + + ctx->round_keys = (uint64_t**)calloc(ctx->nr + 1, sizeof(uint64_t**)); + if (ctx->round_keys == NULL) + perror("Could not allocate memory for cipher round keys."); + + for (i = 0; i < ctx->nr + 1; ++i) { + ctx->round_keys[i] = (uint64_t*)calloc(ctx->nb, sizeof(uint64_t)); + if (ctx->round_keys[i] == NULL) + perror("Could not allocate memory for cipher round keys."); + } + return ctx; +} + + +int KalynaDelete(kalyna_t* ctx) { + int i; + free(ctx->state); + for (i = 0; i < ctx->nr + 1; ++i) { + free(ctx->round_keys[i]); + } + free(ctx->round_keys); + free(ctx); + ctx = NULL; + return 0; +} + + +void SubBytes(kalyna_t* ctx) { + int i; + uint64_t* s = ctx->state; /* For shorter expressions. */ + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = sboxes_enc[0][s[i] & 0x00000000000000FFULL] | + ((uint64_t)sboxes_enc[1][(s[i] & 0x000000000000FF00ULL) >> 8] << 8) | + ((uint64_t)sboxes_enc[2][(s[i] & 0x0000000000FF0000ULL) >> 16] << 16) | + ((uint64_t)sboxes_enc[3][(s[i] & 0x00000000FF000000ULL) >> 24] << 24) | + ((uint64_t)sboxes_enc[0][(s[i] & 0x000000FF00000000ULL) >> 32] << 32) | + ((uint64_t)sboxes_enc[1][(s[i] & 0x0000FF0000000000ULL) >> 40] << 40) | + ((uint64_t)sboxes_enc[2][(s[i] & 0x00FF000000000000ULL) >> 48] << 48) | + ((uint64_t)sboxes_enc[3][(s[i] & 0xFF00000000000000ULL) >> 56] << 56); + } +} + +void InvSubBytes(kalyna_t* ctx) { + int i; + uint64_t* s = ctx->state; /* For shorter expressions. */ + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = sboxes_dec[0][s[i] & 0x00000000000000FFULL] | + ((uint64_t)sboxes_dec[1][(s[i] & 0x000000000000FF00ULL) >> 8] << 8) | + ((uint64_t)sboxes_dec[2][(s[i] & 0x0000000000FF0000ULL) >> 16] << 16) | + ((uint64_t)sboxes_dec[3][(s[i] & 0x00000000FF000000ULL) >> 24] << 24) | + ((uint64_t)sboxes_dec[0][(s[i] & 0x000000FF00000000ULL) >> 32] << 32) | + ((uint64_t)sboxes_dec[1][(s[i] & 0x0000FF0000000000ULL) >> 40] << 40) | + ((uint64_t)sboxes_dec[2][(s[i] & 0x00FF000000000000ULL) >> 48] << 48) | + ((uint64_t)sboxes_dec[3][(s[i] & 0xFF00000000000000ULL) >> 56] << 56); + } +} + + +void ShiftRows(kalyna_t* ctx) { + int row, col; + int shift = -1; + + uint8_t* state = WordsToBytes(ctx->nb, ctx->state); + uint8_t* nstate = (uint8_t*) malloc(ctx->nb * sizeof(uint64_t)); + + for (row = 0; row < sizeof(uint64_t); ++row) { + if (row % (sizeof(uint64_t) / ctx->nb) == 0) + shift += 1; + for (col = 0; col < ctx->nb; ++col) { + INDEX(nstate, row, (col + shift) % ctx->nb) = INDEX(state, row, col); + } + } + + ctx->state = BytesToWords(ctx->nb * sizeof(uint64_t), nstate); + free(state); +} + +void InvShiftRows(kalyna_t* ctx) { + int row, col; + int shift = -1; + + uint8_t* state = WordsToBytes(ctx->nb, ctx->state); + uint8_t* nstate = (uint8_t*) malloc(ctx->nb * sizeof(uint64_t)); + + for (row = 0; row < sizeof(uint64_t); ++row) { + if (row % (sizeof(uint64_t) / ctx->nb) == 0) + shift += 1; + for (col = 0; col < ctx->nb; ++col) { + INDEX(nstate, row, col) = INDEX(state, row, (col + shift) % ctx->nb); + } + } + + ctx->state = BytesToWords(ctx->nb * sizeof(uint64_t), nstate); + free(state); +} + + +uint8_t MultiplyGF(uint8_t x, uint8_t y) { + int i; + uint8_t r = 0; + uint8_t hbit = 0; + for (i = 0; i < kBITS_IN_BYTE; ++i) { + if ((y & 0x1) == 1) + r ^= x; + hbit = x & 0x80; + x <<= 1; + if (hbit == 0x80) + x ^= kREDUCTION_POLYNOMIAL; + y >>= 1; + } + return r; +} + +void MatrixMultiply(kalyna_t* ctx, uint8_t matrix[8][8]) { + int col, row, b; + uint8_t product; + uint64_t result; + uint8_t* state = WordsToBytes(ctx->nb, ctx->state); + + for (col = 0; col < ctx->nb; ++col) { + result = 0; + for (row = sizeof(uint64_t) - 1; row >= 0; --row) { + product = 0; + for (b = sizeof(uint64_t) - 1; b >= 0; --b) { + product ^= MultiplyGF(INDEX(state, b, col), matrix[row][b]); + } + result |= (uint64_t)product << (row * sizeof(uint64_t)); + } + ctx->state[col] = result; + } +} + +void MixColumns(kalyna_t* ctx) { + MatrixMultiply(ctx, mds_matrix); +} + +void InvMixColumns(kalyna_t* ctx) { + MatrixMultiply(ctx, mds_inv_matrix); +} + + +void EncipherRound(kalyna_t* ctx) { + SubBytes(ctx); + ShiftRows(ctx); + MixColumns(ctx); +} + +void DecipherRound(kalyna_t* ctx) { + InvMixColumns(ctx); + InvShiftRows(ctx); + InvSubBytes(ctx); +} + +void AddRoundKey(int round, kalyna_t* ctx) { + int i; + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = ctx->state[i] + ctx->round_keys[round][i]; + } +} + +void SubRoundKey(int round, kalyna_t* ctx) { + int i; + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = ctx->state[i] - ctx->round_keys[round][i]; + } +} + + +void AddRoundKeyExpand(uint64_t* value, kalyna_t* ctx) { + int i; + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = ctx->state[i] + value[i]; + } +} + + +void XorRoundKey(int round, kalyna_t* ctx) { + int i; + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = ctx->state[i] ^ ctx->round_keys[round][i]; + } +} + + +void XorRoundKeyExpand(uint64_t* value, kalyna_t* ctx) { + int i; + for (i = 0; i < ctx->nb; ++i) { + ctx->state[i] = ctx->state[i] ^ value[i]; + } +} + + +void Rotate(size_t state_size, uint64_t* state_value) { + int i; + uint64_t temp = state_value[0]; + for (i = 1; i < state_size; ++i) { + state_value[i - 1] = state_value[i]; + } + state_value[state_size - 1] = temp; +} + + +void ShiftLeft(size_t state_size, uint64_t* state_value) { + int i; + for (i = 0; i < state_size; ++i) { + state_value[i] <<= 1; + } +} + +void RotateLeft(size_t state_size, uint64_t* state_value) { + size_t rotate_bytes = 2 * state_size + 3; + size_t bytes_num = state_size * (kBITS_IN_WORD / kBITS_IN_BYTE); + + uint8_t* bytes = WordsToBytes(state_size, state_value); + uint8_t* buffer = (uint8_t*) malloc(rotate_bytes); + + /* Rotate bytes in memory. */ + memcpy(buffer, bytes, rotate_bytes); + memmove(bytes, bytes + rotate_bytes, bytes_num - rotate_bytes); + memcpy(bytes + bytes_num - rotate_bytes, buffer, rotate_bytes); + + state_value = BytesToWords(bytes_num, bytes); + + free(buffer); +} + + +void KeyExpandKt(uint64_t* key, kalyna_t* ctx, uint64_t* kt) { + uint64_t* k0 = (uint64_t*) malloc(ctx->nb * sizeof(uint64_t)); + uint64_t* k1 = (uint64_t*) malloc(ctx->nb * sizeof(uint64_t)); + + memset(ctx->state, 0, ctx->nb * sizeof(uint64_t)); + ctx->state[0] += ctx->nb + ctx->nk + 1; + + if (ctx->nb == ctx->nk) { + memcpy(k0, key, ctx->nb * sizeof(uint64_t)); + memcpy(k1, key, ctx->nb * sizeof(uint64_t)); + } else { + memcpy(k0, key, ctx->nb * sizeof(uint64_t)); + memcpy(k1, key + ctx->nb, ctx->nb * sizeof(uint64_t)); + } + + AddRoundKeyExpand(k0, ctx); + EncipherRound(ctx); + XorRoundKeyExpand(k1, ctx); + EncipherRound(ctx); + AddRoundKeyExpand(k0, ctx); + EncipherRound(ctx); + memcpy(kt, ctx->state, ctx->nb * sizeof(uint64_t)); + + free(k0); + free(k1); +} + + +void KeyExpandEven(uint64_t* key, uint64_t* kt, kalyna_t* ctx) { + int i; + uint64_t* initial_data = (uint64_t*) malloc(ctx->nk * sizeof(uint64_t)); + uint64_t* kt_round = (uint64_t*) malloc(ctx->nb * sizeof(uint64_t)); + uint64_t* tmv = (uint64_t*) malloc(ctx->nb * sizeof(uint64_t)); + size_t round = 0; + + memcpy(initial_data, key, ctx->nk * sizeof(uint64_t)); + for (i = 0; i < ctx->nb; ++i) { + tmv[i] = 0x0001000100010001; + } + + while(TRUE) { + memcpy(ctx->state, kt, ctx->nb * sizeof(uint64_t)); + AddRoundKeyExpand(tmv, ctx); + memcpy(kt_round, ctx->state, ctx->nb * sizeof(uint64_t)); + + memcpy(ctx->state, initial_data, ctx->nb * sizeof(uint64_t)); + + AddRoundKeyExpand(kt_round, ctx); + EncipherRound(ctx); + XorRoundKeyExpand(kt_round, ctx); + EncipherRound(ctx); + AddRoundKeyExpand(kt_round, ctx); + + memcpy(ctx->round_keys[round], ctx->state, ctx->nb * sizeof(uint64_t)); + + if (ctx->nr == round) + break; + + if (ctx->nk != ctx->nb) { + round += 2; + + ShiftLeft(ctx->nb, tmv); + + memcpy(ctx->state, kt, ctx->nb * sizeof(uint64_t)); + AddRoundKeyExpand(tmv, ctx); + memcpy(kt_round, ctx->state, ctx->nb * sizeof(uint64_t)); + + memcpy(ctx->state, initial_data + ctx->nb, ctx->nb * sizeof(uint64_t)); + + AddRoundKeyExpand(kt_round, ctx); + EncipherRound(ctx); + XorRoundKeyExpand(kt_round, ctx); + EncipherRound(ctx); + AddRoundKeyExpand(kt_round, ctx); + + memcpy(ctx->round_keys[round], ctx->state, ctx->nb * sizeof(uint64_t)); + + if (ctx->nr == round) + break; + } + round += 2; + ShiftLeft(ctx->nb, tmv); + Rotate(ctx->nk, initial_data); + } + + free(initial_data); + free(kt_round); + free(tmv); +} + +void KeyExpandOdd(kalyna_t* ctx) { + int i; + for (i = 1; i < ctx->nr; i += 2) { + memcpy(ctx->round_keys[i], ctx->round_keys[i - 1], ctx->nb * sizeof(uint64_t)); + RotateLeft(ctx->nb, ctx->round_keys[i]); + } +} + +void KalynaKeyExpand(uint64_t* key, kalyna_t* ctx) { + uint64_t* kt = (uint64_t*) malloc(ctx->nb * sizeof(uint64_t)); + KeyExpandKt(key, ctx, kt); + KeyExpandEven(key, kt, ctx); + KeyExpandOdd(ctx); + free(kt); +} + + +void KalynaEncipher(uint64_t* plaintext, kalyna_t* ctx, uint64_t* ciphertext) { + int round = 0; + memcpy(ctx->state, plaintext, ctx->nb * sizeof(uint64_t)); + + AddRoundKey(round, ctx); + for (round = 1; round < ctx->nr; ++round) { + EncipherRound(ctx); + XorRoundKey(round, ctx); + } + EncipherRound(ctx); + AddRoundKey(ctx->nr, ctx); + + memcpy(ciphertext, ctx->state, ctx->nb * sizeof(uint64_t)); +} + +void KalynaDecipher(uint64_t* ciphertext, kalyna_t* ctx, uint64_t* plaintext) { + int round = ctx->nr; + memcpy(ctx->state, ciphertext, ctx->nb * sizeof(uint64_t)); + + SubRoundKey(round, ctx); + for (round = ctx->nr - 1; round > 0; --round) { + DecipherRound(ctx); + XorRoundKey(round, ctx); + } + DecipherRound(ctx); + SubRoundKey(0, ctx); + + memcpy(plaintext, ctx->state, ctx->nb * sizeof(uint64_t)); +} + + +uint8_t* WordsToBytes(size_t length, uint64_t* words) { + int i; + uint8_t* bytes; + if (IsBigEndian()) { + for (i = 0; i < length; ++i) { + words[i] = ReverseWord(words[i]); + } + } + bytes = (uint8_t*)words; + return bytes; +} + +uint64_t* BytesToWords(size_t length, uint8_t* bytes) { + int i; + uint64_t* words = (uint64_t*)bytes; + if (IsBigEndian()) { + for (i = 0; i < length; ++i) { + words[i] = ReverseWord(words[i]); + } + } + return words; +} + + +uint64_t ReverseWord(uint64_t word) { + int i; + uint64_t reversed = 0; + uint8_t* src = (uint8_t*)&word; + uint8_t* dst = (uint8_t*)&reversed; + + for (i = 0; i < sizeof(uint64_t); ++i) { + dst[i] = src[sizeof(uint64_t) - i]; + } + return reversed; +} + + +int IsBigEndian() { + unsigned int num = 1; + /* Check the least significant byte value to determine endianness */ + return (*((uint8_t*)&num) == 0); +} + +void PrintState(size_t length, uint64_t* state) { + int i; + for (i = length - 1; i >= 0; --i) { + printf("%16.16llx", state[i]); + } + printf("\n"); +} + diff --git a/kalyna.h b/kalyna.h new file mode 100644 index 0000000..4f869b0 --- /dev/null +++ b/kalyna.h @@ -0,0 +1,87 @@ +/* + +Header file for the reference implementation of the Kalyna block cipher (DSTU 7624:2014), all block and key length variants + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#ifndef KALYNA_H +#define KALYNA_H + + +#include +#include + + +typedef unsigned char uint8_t; +typedef unsigned long long uint64_t; + +/*! + * Context to store Kalyna cipher parameters. + */ +typedef struct { + size_t nb; /**< Number of 64-bit words in enciphering block. */ + size_t nk; /**< Number of 64-bit words in key. */ + size_t nr; /**< Number of enciphering rounds. */ + uint64_t* state; /**< Current cipher state. */ + uint64_t** round_keys; /**< Round key computed from enciphering key. */ +} kalyna_t; + + +/*! + * Initialize Kalyna parameters and create cipher context. + * + * @param block_size Enciphering block bit size (128, 256 or 512 bit sizes are + * allowed). + * @param block_size Enciphering key bit size. Must be equal or double the + * block bit size. + * @return Pointer to Kalyna context containing cipher instance + * parameters and allocated memory for state and round keys. NULL in case of + * error. + */ +kalyna_t* KalynaInit(size_t block_size, size_t key_size); + +/*! + * Delete Kalyna cipher context and free used memory. + * + * @param ctx Kalyna cipher context. + * @return Zero in case of success. + */ +int KalynaDelete(kalyna_t* ctx); + +/*! + * Compute round keys given the enciphering key and store them in cipher + * context `ctx`. + * + * @param key Kalyna enciphering key. + * @param ctx Initialized cipher context. + */ +void KalynaKeyExpand(uint64_t* key, kalyna_t* ctx); + +/*! + * Encipher plaintext using Kalyna symmetric block cipher. + * KalynaInit() function with appropriate block and enciphering key sizes must + * be called beforehand to get the cipher context `ctx`. After all enciphering + * is completed KalynaDelete() must be called to free up allocated memory. + * + * @param plaintext Plaintext of length Nb words for enciphering. + * @param ctx Initialized cipher context with precomputed round keys. + * @param ciphertext The result of enciphering. + */ +void KalynaEncipher(uint64_t* plaintext, kalyna_t* ctx, uint64_t* ciphertext); + +/*! + * Decipher ciphertext using Kalyna symmetric block cipher. + * KalynaInit() function with appropriate block and enciphering key sizes must + * be called beforehand to get the cipher context `ctx`. After all enciphering + * is completed KalynaDelete() must be called to free up allocated memory. + * + * @param ciphertext Enciphered data of length Nb words. + * @param ctx Initialized cipher context with precomputed round keys. + * @param plaintext The result of deciphering. + */ +void KalynaDecipher(uint64_t* ciphertext, kalyna_t* ctx, uint64_t* plaintext); + +#endif /* KALYNA_H */ + diff --git a/main.c b/main.c new file mode 100644 index 0000000..618a0a7 --- /dev/null +++ b/main.c @@ -0,0 +1,326 @@ +/* + +main.c, printing test vectors of reference implementation of the Kalyna block cipher (DSTU 7624:2014), all block and key length variants + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#include +#include + +#include "kalyna.h" +#include "transformations.h" + +void print (int data_size, uint64_t data []); + +int main(int argc, char** argv) { + + int i; + kalyna_t* ctx22_e = KalynaInit(128, 128); + kalyna_t* ctx24_e = KalynaInit(128, 256); + kalyna_t* ctx44_e = KalynaInit(256, 256); + kalyna_t* ctx48_e = KalynaInit(256, 512); + kalyna_t* ctx88_e = KalynaInit(512, 512); + + uint64_t pt22_e[2] = {0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL}; + uint64_t ct22_e[2]; + uint64_t key22_e[2] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL}; + uint64_t expect22_e[2] = {0x20ac9b777d1cbf81ULL, 0x06add2b439eac9e1ULL}; + + uint64_t pt24_e[2] = {0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL}; + uint64_t ct24_e[2]; + uint64_t key24_e[4] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL}; + uint64_t expect24_e[2] = { 0x8a150010093eec58ULL, 0x144f336f16f74811ULL}; + + uint64_t pt44_e[4] = {0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL}; + uint64_t ct44_e[4]; + uint64_t key44_e[4] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL}; + uint64_t expect44_e[4] = {0x3521c90e573d6ef6ULL, 0x8c2abddc23e3daaeULL, 0x5a0d6a20ec6339a0ULL, 0x2cd97f61245c3888ULL}; + + uint64_t pt48_e[4] = {0x4746454443424140ULL, 0x4f4e4d4c4b4a4948ULL, 0x5756555453525150ULL, 0x5f5e5d5c5b5a5958ULL}; + uint64_t ct48_e[4]; + uint64_t key48_e[8] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL, + 0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL}; + uint64_t expect48_e[4] = {0x7ab6b7e6e9906960ULL, 0xb76822d793d8d64bULL, 0x02e1d73c3cc8028eULL, 0xd95dfefda8742efdULL}; + + + uint64_t pt88_e[8] = { 0x4746454443424140ULL, 0x4f4e4d4c4b4a4948ULL, 0x5756555453525150ULL, 0x5f5e5d5c5b5a5958ULL, + 0x6766656463626160ULL, 0x6f6e6d6c6b6a6968ULL, 0x7776757473727170ULL, 0x7f7e7d7c7b7a7978ULL}; + uint64_t ct88_e[8]; + uint64_t key88_e[8] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL, + 0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL}; + uint64_t expect88_e[8] = { 0x6a351c811be3264aULL, 0x1a239605cad61da6ULL, 0xa1f347aa5483ba67ULL, 0xb856eb20c3ee1d3eULL, + 0x66ab5b1717f4d095ULL, 0x6cc815bb34f1d62fULL, 0xb7fe6e85266a90cbULL, 0xd9d90d947264bcc5ULL}; + + uint64_t ct22_d[2] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL}; + uint64_t pt22_d[2]; + uint64_t key22_d[2] = {0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL}; + uint64_t expect22_d[2] = {0x84c70c472bef9172ULL, 0xd7da733930c2096fULL}; + + uint64_t ct24_d[2] = {0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL}; + uint64_t pt24_d[2]; + uint64_t key24_d[4] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL}; + uint64_t expect24_d[2] = {0xe1dffdce56b46df3ULL, 0x96d9ca30705f5bb4ULL}; + + uint64_t ct44_d[4] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL}; + uint64_t pt44_d[4]; + uint64_t key44_d[4] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL}; + uint64_t expect44_d[4] = {0x864e67967823c57fULL, 0xa34b8b3fb0e9c103ULL, 0xd3c33f2c597c5babULL, 0xe30fb28625d1ed61ULL}; + + uint64_t ct48_d[4] = {0x58595a5b5c5d5e5fULL, 0x5051525354555657ULL, 0x48494a4b4c4d4e4fULL, 0x4041424344454647ULL}; + uint64_t pt48_d[4]; + uint64_t key48_d[8] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL, + 0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL}; + uint64_t expect48_d[4] = {0x82d4da67277a3118ULL, 0x078d78a1b907cdbcULL, 0x97845f9e1898705eULL, 0xe06aba796d910b2dULL}; + + uint64_t ct88_d[8] = {0x78797a7b7c7d7e7fULL, 0x7071727374757677ULL, 0x68696a6b6c6d6e6fULL, 0x6061626364656667ULL, + 0x58595a5b5c5d5e5fULL, 0x5051525354555657ULL, 0x48494a4b4c4d4e4fULL, 0x4041424344454647ULL}; + uint64_t pt88_d[8]; + uint64_t key88_d[8] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL, + 0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL}; + uint64_t expect88_d[8] = {0x5252a025338480ceULL, 0x29d8a9e614d7ea1bULL, 0xbd45a8e90e1e38fdULL, 0xa346fad954450492ULL, + 0xf2b13b85dbef7f75ULL, 0x6ae6753b839dff97ULL, 0xdc1b29b5ab5741afULL, 0x22ff5aaa13bb94f0ULL }; + + kalyna_t* ctx22_d = KalynaInit(128, 128); + kalyna_t* ctx24_d = KalynaInit(128, 256); + kalyna_t* ctx44_d = KalynaInit(256, 256); + kalyna_t* ctx48_d = KalynaInit(256, 512); + kalyna_t* ctx88_d = KalynaInit(512, 512); + + // kalyna 22 enc + KalynaKeyExpand(key22_e, ctx22_e); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx22_e->nb * 64, ctx22_e->nk * 64); + + printf("\n--- ENCIPHERING ---\n"); + printf("Key:\n"); + print(ctx22_e->nk, key22_e); + + printf("Plaintext:\n"); + print(ctx22_e->nb, pt22_e); + + KalynaEncipher(pt22_e, ctx22_e, ct22_e); + printf("Ciphertext:\n"); + print(ctx22_e->nb, ct22_e); + + if (memcmp(ct22_e, expect22_e, sizeof(ct22_e)) != 0) printf("Failed enciphering\n"); + else printf("Success enciphering\n\n"); + + KalynaDelete(ctx22_e); + + // kalyna 22 dec + KalynaKeyExpand(key22_d, ctx22_d); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx22_d->nb * 64, ctx22_d->nk * 64); + + printf("\n--- DECIPHERING ---\n"); + printf("Key:\n"); + print(ctx22_d->nk, key22_d); + + printf("Ciphertext:\n"); + print(ctx22_d->nb, ct22_d); + + KalynaDecipher(ct22_d, ctx22_d, pt22_d); + printf("Plaintext:\n"); + print(ctx22_d->nb, pt22_d); + + if (memcmp(pt22_d, expect22_d, sizeof(pt22_d)) != 0) printf("Failed deciphering\n"); + else printf("Success deciphering\n\n"); + + KalynaDelete(ctx22_d); + + // kalyna 24 enc + KalynaKeyExpand(key24_e, ctx24_e); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx24_e->nb * 64, ctx24_e->nk * 64); + + printf("\n--- ENCIPHERING ---\n"); + printf("Key:\n"); + print(ctx24_e->nk, key24_e); + + printf("Plaintext:\n"); + print(ctx24_e->nb, pt24_e); + + KalynaEncipher(pt24_e, ctx24_e, ct24_e); + printf("Ciphertext:\n"); + print(ctx24_e->nb, ct24_e); + + if (memcmp(ct24_e, expect24_e, sizeof(ct24_e)) != 0) printf("Failed enciphering\n"); + else printf("Success enciphering\n\n"); + + KalynaDelete(ctx24_e); + + // kalyna 24 dec + KalynaKeyExpand(key24_d, ctx24_d); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx24_d->nb * 64, ctx24_d->nk * 64); + + printf("\n--- DECIPHERING ---\n"); + printf("Key:\n"); + print(ctx24_d->nk, key24_d); + + printf("Ciphertext:\n"); + print(ctx24_d->nb, ct24_d); + + KalynaDecipher(ct24_d, ctx24_d, pt24_d); + printf("Plaintext:\n"); + print(ctx24_d->nb, pt24_d); + + if (memcmp(pt24_d, expect24_d, sizeof(pt24_d)) != 0) printf("Failed deciphering\n"); + else printf("Success deciphering\n\n"); + + KalynaDelete(ctx24_d); + + // kalyna 44 enc + KalynaKeyExpand(key44_e, ctx44_e); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx44_e->nb * 64, ctx44_e->nk * 64); + + printf("\n--- ENCIPHERING ---\n"); + printf("Key:\n"); + print(ctx44_e->nk, key44_e); + + printf("Plaintext:\n"); + print(ctx44_e->nb, pt44_e); + + KalynaEncipher(pt44_e, ctx44_e, ct44_e); + printf("Ciphertext:\n"); + print(ctx44_e->nb, ct44_e); + + if (memcmp(ct44_e, expect44_e, sizeof(ct44_e)) != 0) printf("Failed enciphering\n"); + else printf("Success enciphering\n\n"); + + KalynaDelete(ctx44_e); + + // kalyna 44 dec + KalynaKeyExpand(key44_d, ctx44_d); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx44_d->nb * 64, ctx44_d->nk * 64); + + printf("\n--- DECIPHERING ---\n"); + printf("Key:\n"); + print(ctx44_d->nk, key44_d); + + printf("Ciphertext:\n"); + print(ctx44_d->nb, ct44_d); + + KalynaDecipher(ct44_d, ctx44_d, pt44_d); + printf("Plaintext:\n"); + print(ctx44_d->nb, pt44_d); + + if (memcmp(pt44_d, expect44_d, sizeof(pt44_d)) != 0) printf("Failed deciphering\n"); + else printf("Success deciphering\n\n"); + + KalynaDelete(ctx44_d); + + // kalyna 48 enc + KalynaKeyExpand(key48_e, ctx48_e); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx48_e->nb * 64, ctx48_e->nk * 64); + + printf("\n--- ENCIPHERING ---\n"); + printf("Key:\n"); + print(ctx48_e->nk, key48_e); + + printf("Plaintext:\n"); + print(ctx48_e->nb, pt48_e); + + KalynaEncipher(pt48_e, ctx48_e, ct48_e); + printf("Ciphertext:\n"); + print(ctx48_e->nb, ct48_e); + + if (memcmp(ct48_e, expect48_e, sizeof(ct48_e)) != 0) printf("Failed enciphering\n"); + else printf("Success enciphering\n\n"); + + KalynaDelete(ctx48_e); + + // kalyna 48 dec + KalynaKeyExpand(key48_d, ctx48_d); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx48_d->nb * 64, ctx48_d->nk * 64); + + printf("\n--- DECIPHERING ---\n"); + printf("Key:\n"); + print(ctx48_d->nk, key48_d); + + printf("Ciphertext:\n"); + print(ctx48_d->nb, ct48_d); + + KalynaDecipher(ct48_d, ctx48_d, pt48_d); + printf("Plaintext:\n"); + print(ctx48_d->nb, pt48_d); + + if (memcmp(pt48_d, expect48_d, sizeof(pt48_d)) != 0) printf("Failed deciphering\n"); + else printf("Success deciphering\n\n"); + + KalynaDelete(ctx48_d); + + // kalyna 88 enc + KalynaKeyExpand(key88_e, ctx88_e); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx88_e->nb * 64, ctx88_e->nk * 64); + + printf("\n--- ENCIPHERING ---\n"); + printf("Key:\n"); + print(ctx88_e->nk, key88_e); + + printf("Plaintext:\n"); + print(ctx88_e->nb, pt88_e); + + KalynaEncipher(pt88_e, ctx88_e, ct88_e); + printf("Ciphertext:\n"); + print(ctx88_e->nb, ct88_e); + + if (memcmp(ct88_e, expect88_e, sizeof(ct88_e)) != 0) printf("Failed enciphering\n"); + else printf("Success enciphering\n\n"); + + KalynaDelete(ctx88_e); + + // kalyna 88 dec + KalynaKeyExpand(key88_d, ctx88_d); + + printf("\n=============\n"); + printf("Kalyna (%lu, %lu)\n", ctx88_d->nb * 64, ctx88_d->nk * 64); + + printf("\n--- DECIPHERING ---\n"); + printf("Key:\n"); + print(ctx88_d->nk, key88_d); + + printf("Ciphertext:\n"); + print(ctx88_d->nb, ct88_d); + + KalynaDecipher(ct88_d, ctx88_d, pt88_d); + printf("Plaintext:\n"); + print(ctx88_d->nb, pt88_d); + + if (memcmp(pt88_d, expect88_d, sizeof(pt88_d)) != 0) printf("Failed deciphering\n"); + else printf("Success deciphering\n\n"); + + KalynaDelete(ctx88_d); + + return 0; +} + + +void print (int data_size, uint64_t data []) +{ + int i; + uint8_t * tmp = (uint8_t *) data; + for (i = 0; i < data_size * 8; i ++) + { + if (! (i % 16)) printf (" "); + printf ("%02X", (unsigned int) tmp [i]); + if (!((i + 1) % 16)) printf ("\n"); + }; + printf ("\n"); +}; diff --git a/makefile b/makefile new file mode 100644 index 0000000..b7f701d --- /dev/null +++ b/makefile @@ -0,0 +1,4 @@ +all:kalyna-reference +kalyna-reference: kalyna.c kalyna.h main.c makefile tables.c tables.h transformations.h + gcc kalyna.c main.c tables.c -o kalyna-reference + ./kalyna-reference diff --git a/tables.c b/tables.c new file mode 100644 index 0000000..a7da870 --- /dev/null +++ b/tables.c @@ -0,0 +1,183 @@ +/* + +S-boxes and MDS-matrices for the reference implementation of the Kalyna block cipher (DSTU 7624:2014) + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#include "kalyna.h" + +uint8_t mds_matrix[8][8] = { + { 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04 }, + { 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07 }, + { 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06 }, + { 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08 }, + { 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01 }, + { 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05 }, + { 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01 }, + { 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01 } +}; + +uint8_t mds_inv_matrix[8][8] = { + {0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA}, + {0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7}, + {0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49}, + {0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F}, + {0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8}, + {0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76}, + {0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95}, + {0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD} +}; + +uint8_t sboxes_enc[4][256] = { +{ + 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09, + 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39, + 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6, + 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1, + 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27, + 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41, + 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e, + 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55, + 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff, + 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1, + 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76, + 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26, + 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82, + 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8, + 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d, + 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80 +}, +{ + 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8, + 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d, + 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d, + 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc, + 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee, + 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca, + 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20, + 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f, + 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51, + 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98, + 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9, + 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05, + 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82, + 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad, + 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59, + 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7 +}, +{ + 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59, + 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1, + 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72, + 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90, + 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35, + 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48, + 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38, + 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33, + 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29, + 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83, + 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2, + 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43, + 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82, + 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91, + 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44, + 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67 +}, +{ + 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f, + 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd, + 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66, + 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf, + 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99, + 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71, + 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60, + 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b, + 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09, + 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2, + 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7, + 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a, + 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39, + 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef, + 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36, + 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61 +} +}; + + +uint8_t sboxes_dec[4][256] = { +{ + 0xa4, 0xa2, 0xa9, 0xc5, 0x4e, 0xc9, 0x03, 0xd9, 0x7e, 0x0f, 0xd2, 0xad, 0xe7, 0xd3, 0x27, 0x5b, + 0xe3, 0xa1, 0xe8, 0xe6, 0x7c, 0x2a, 0x55, 0x0c, 0x86, 0x39, 0xd7, 0x8d, 0xb8, 0x12, 0x6f, 0x28, + 0xcd, 0x8a, 0x70, 0x56, 0x72, 0xf9, 0xbf, 0x4f, 0x73, 0xe9, 0xf7, 0x57, 0x16, 0xac, 0x50, 0xc0, + 0x9d, 0xb7, 0x47, 0x71, 0x60, 0xc4, 0x74, 0x43, 0x6c, 0x1f, 0x93, 0x77, 0xdc, 0xce, 0x20, 0x8c, + 0x99, 0x5f, 0x44, 0x01, 0xf5, 0x1e, 0x87, 0x5e, 0x61, 0x2c, 0x4b, 0x1d, 0x81, 0x15, 0xf4, 0x23, + 0xd6, 0xea, 0xe1, 0x67, 0xf1, 0x7f, 0xfe, 0xda, 0x3c, 0x07, 0x53, 0x6a, 0x84, 0x9c, 0xcb, 0x02, + 0x83, 0x33, 0xdd, 0x35, 0xe2, 0x59, 0x5a, 0x98, 0xa5, 0x92, 0x64, 0x04, 0x06, 0x10, 0x4d, 0x1c, + 0x97, 0x08, 0x31, 0xee, 0xab, 0x05, 0xaf, 0x79, 0xa0, 0x18, 0x46, 0x6d, 0xfc, 0x89, 0xd4, 0xc7, + 0xff, 0xf0, 0xcf, 0x42, 0x91, 0xf8, 0x68, 0x0a, 0x65, 0x8e, 0xb6, 0xfd, 0xc3, 0xef, 0x78, 0x4c, + 0xcc, 0x9e, 0x30, 0x2e, 0xbc, 0x0b, 0x54, 0x1a, 0xa6, 0xbb, 0x26, 0x80, 0x48, 0x94, 0x32, 0x7d, + 0xa7, 0x3f, 0xae, 0x22, 0x3d, 0x66, 0xaa, 0xf6, 0x00, 0x5d, 0xbd, 0x4a, 0xe0, 0x3b, 0xb4, 0x17, + 0x8b, 0x9f, 0x76, 0xb0, 0x24, 0x9a, 0x25, 0x63, 0xdb, 0xeb, 0x7a, 0x3e, 0x5c, 0xb3, 0xb1, 0x29, + 0xf2, 0xca, 0x58, 0x6e, 0xd8, 0xa8, 0x2f, 0x75, 0xdf, 0x14, 0xfb, 0x13, 0x49, 0x88, 0xb2, 0xec, + 0xe4, 0x34, 0x2d, 0x96, 0xc6, 0x3a, 0xed, 0x95, 0x0e, 0xe5, 0x85, 0x6b, 0x40, 0x21, 0x9b, 0x09, + 0x19, 0x2b, 0x52, 0xde, 0x45, 0xa3, 0xfa, 0x51, 0xc2, 0xb5, 0xd1, 0x90, 0xb9, 0xf3, 0x37, 0xc1, + 0x0d, 0xba, 0x41, 0x11, 0x38, 0x7b, 0xbe, 0xd0, 0xd5, 0x69, 0x36, 0xc8, 0x62, 0x1b, 0x82, 0x8f +}, +{ + 0x83, 0xf2, 0x2a, 0xeb, 0xe9, 0xbf, 0x7b, 0x9c, 0x34, 0x96, 0x8d, 0x98, 0xb9, 0x69, 0x8c, 0x29, + 0x3d, 0x88, 0x68, 0x06, 0x39, 0x11, 0x4c, 0x0e, 0xa0, 0x56, 0x40, 0x92, 0x15, 0xbc, 0xb3, 0xdc, + 0x6f, 0xf8, 0x26, 0xba, 0xbe, 0xbd, 0x31, 0xfb, 0xc3, 0xfe, 0x80, 0x61, 0xe1, 0x7a, 0x32, 0xd2, + 0x70, 0x20, 0xa1, 0x45, 0xec, 0xd9, 0x1a, 0x5d, 0xb4, 0xd8, 0x09, 0xa5, 0x55, 0x8e, 0x37, 0x76, + 0xa9, 0x67, 0x10, 0x17, 0x36, 0x65, 0xb1, 0x95, 0x62, 0x59, 0x74, 0xa3, 0x50, 0x2f, 0x4b, 0xc8, + 0xd0, 0x8f, 0xcd, 0xd4, 0x3c, 0x86, 0x12, 0x1d, 0x23, 0xef, 0xf4, 0x53, 0x19, 0x35, 0xe6, 0x7f, + 0x5e, 0xd6, 0x79, 0x51, 0x22, 0x14, 0xf7, 0x1e, 0x4a, 0x42, 0x9b, 0x41, 0x73, 0x2d, 0xc1, 0x5c, + 0xa6, 0xa2, 0xe0, 0x2e, 0xd3, 0x28, 0xbb, 0xc9, 0xae, 0x6a, 0xd1, 0x5a, 0x30, 0x90, 0x84, 0xf9, + 0xb2, 0x58, 0xcf, 0x7e, 0xc5, 0xcb, 0x97, 0xe4, 0x16, 0x6c, 0xfa, 0xb0, 0x6d, 0x1f, 0x52, 0x99, + 0x0d, 0x4e, 0x03, 0x91, 0xc2, 0x4d, 0x64, 0x77, 0x9f, 0xdd, 0xc4, 0x49, 0x8a, 0x9a, 0x24, 0x38, + 0xa7, 0x57, 0x85, 0xc7, 0x7c, 0x7d, 0xe7, 0xf6, 0xb7, 0xac, 0x27, 0x46, 0xde, 0xdf, 0x3b, 0xd7, + 0x9e, 0x2b, 0x0b, 0xd5, 0x13, 0x75, 0xf0, 0x72, 0xb6, 0x9d, 0x1b, 0x01, 0x3f, 0x44, 0xe5, 0x87, + 0xfd, 0x07, 0xf1, 0xab, 0x94, 0x18, 0xea, 0xfc, 0x3a, 0x82, 0x5f, 0x05, 0x54, 0xdb, 0x00, 0x8b, + 0xe3, 0x48, 0x0c, 0xca, 0x78, 0x89, 0x0a, 0xff, 0x3e, 0x5b, 0x81, 0xee, 0x71, 0xe2, 0xda, 0x2c, + 0xb8, 0xb5, 0xcc, 0x6e, 0xa8, 0x6b, 0xad, 0x60, 0xc6, 0x08, 0x04, 0x02, 0xe8, 0xf5, 0x4f, 0xa4, + 0xf3, 0xc0, 0xce, 0x43, 0x25, 0x1c, 0x21, 0x33, 0x0f, 0xaf, 0x47, 0xed, 0x66, 0x63, 0x93, 0xaa +}, +{ + 0x45, 0xd4, 0x0b, 0x43, 0xf1, 0x72, 0xed, 0xa4, 0xc2, 0x38, 0xe6, 0x71, 0xfd, 0xb6, 0x3a, 0x95, + 0x50, 0x44, 0x4b, 0xe2, 0x74, 0x6b, 0x1e, 0x11, 0x5a, 0xc6, 0xb4, 0xd8, 0xa5, 0x8a, 0x70, 0xa3, + 0xa8, 0xfa, 0x05, 0xd9, 0x97, 0x40, 0xc9, 0x90, 0x98, 0x8f, 0xdc, 0x12, 0x31, 0x2c, 0x47, 0x6a, + 0x99, 0xae, 0xc8, 0x7f, 0xf9, 0x4f, 0x5d, 0x96, 0x6f, 0xf4, 0xb3, 0x39, 0x21, 0xda, 0x9c, 0x85, + 0x9e, 0x3b, 0xf0, 0xbf, 0xef, 0x06, 0xee, 0xe5, 0x5f, 0x20, 0x10, 0xcc, 0x3c, 0x54, 0x4a, 0x52, + 0x94, 0x0e, 0xc0, 0x28, 0xf6, 0x56, 0x60, 0xa2, 0xe3, 0x0f, 0xec, 0x9d, 0x24, 0x83, 0x7e, 0xd5, + 0x7c, 0xeb, 0x18, 0xd7, 0xcd, 0xdd, 0x78, 0xff, 0xdb, 0xa1, 0x09, 0xd0, 0x76, 0x84, 0x75, 0xbb, + 0x1d, 0x1a, 0x2f, 0xb0, 0xfe, 0xd6, 0x34, 0x63, 0x35, 0xd2, 0x2a, 0x59, 0x6d, 0x4d, 0x77, 0xe7, + 0x8e, 0x61, 0xcf, 0x9f, 0xce, 0x27, 0xf5, 0x80, 0x86, 0xc7, 0xa6, 0xfb, 0xf8, 0x87, 0xab, 0x62, + 0x3f, 0xdf, 0x48, 0x00, 0x14, 0x9a, 0xbd, 0x5b, 0x04, 0x92, 0x02, 0x25, 0x65, 0x4c, 0x53, 0x0c, + 0xf2, 0x29, 0xaf, 0x17, 0x6c, 0x41, 0x30, 0xe9, 0x93, 0x55, 0xf7, 0xac, 0x68, 0x26, 0xc4, 0x7d, + 0xca, 0x7a, 0x3e, 0xa0, 0x37, 0x03, 0xc1, 0x36, 0x69, 0x66, 0x08, 0x16, 0xa7, 0xbc, 0xc5, 0xd3, + 0x22, 0xb7, 0x13, 0x46, 0x32, 0xe8, 0x57, 0x88, 0x2b, 0x81, 0xb2, 0x4e, 0x64, 0x1c, 0xaa, 0x91, + 0x58, 0x2e, 0x9b, 0x5c, 0x1b, 0x51, 0x73, 0x42, 0x23, 0x01, 0x6e, 0xf3, 0x0d, 0xbe, 0x3d, 0x0a, + 0x2d, 0x1f, 0x67, 0x33, 0x19, 0x7b, 0x5e, 0xea, 0xde, 0x8b, 0xcb, 0xa9, 0x8c, 0x8d, 0xad, 0x49, + 0x82, 0xe4, 0xba, 0xc3, 0x15, 0xd1, 0xe0, 0x89, 0xfc, 0xb1, 0xb9, 0xb5, 0x07, 0x79, 0xb8, 0xe1 +}, +{ + 0xb2, 0xb6, 0x23, 0x11, 0xa7, 0x88, 0xc5, 0xa6, 0x39, 0x8f, 0xc4, 0xe8, 0x73, 0x22, 0x43, 0xc3, + 0x82, 0x27, 0xcd, 0x18, 0x51, 0x62, 0x2d, 0xf7, 0x5c, 0x0e, 0x3b, 0xfd, 0xca, 0x9b, 0x0d, 0x0f, + 0x79, 0x8c, 0x10, 0x4c, 0x74, 0x1c, 0x0a, 0x8e, 0x7c, 0x94, 0x07, 0xc7, 0x5e, 0x14, 0xa1, 0x21, + 0x57, 0x50, 0x4e, 0xa9, 0x80, 0xd9, 0xef, 0x64, 0x41, 0xcf, 0x3c, 0xee, 0x2e, 0x13, 0x29, 0xba, + 0x34, 0x5a, 0xae, 0x8a, 0x61, 0x33, 0x12, 0xb9, 0x55, 0xa8, 0x15, 0x05, 0xf6, 0x03, 0x06, 0x49, + 0xb5, 0x25, 0x09, 0x16, 0x0c, 0x2a, 0x38, 0xfc, 0x20, 0xf4, 0xe5, 0x7f, 0xd7, 0x31, 0x2b, 0x66, + 0x6f, 0xff, 0x72, 0x86, 0xf0, 0xa3, 0x2f, 0x78, 0x00, 0xbc, 0xcc, 0xe2, 0xb0, 0xf1, 0x42, 0xb4, + 0x30, 0x5f, 0x60, 0x04, 0xec, 0xa5, 0xe3, 0x8b, 0xe7, 0x1d, 0xbf, 0x84, 0x7b, 0xe6, 0x81, 0xf8, + 0xde, 0xd8, 0xd2, 0x17, 0xce, 0x4b, 0x47, 0xd6, 0x69, 0x6c, 0x19, 0x99, 0x9a, 0x01, 0xb3, 0x85, + 0xb1, 0xf9, 0x59, 0xc2, 0x37, 0xe9, 0xc8, 0xa0, 0xed, 0x4f, 0x89, 0x68, 0x6d, 0xd5, 0x26, 0x91, + 0x87, 0x58, 0xbd, 0xc9, 0x98, 0xdc, 0x75, 0xc0, 0x76, 0xf5, 0x67, 0x6b, 0x7e, 0xeb, 0x52, 0xcb, + 0xd1, 0x5b, 0x9f, 0x0b, 0xdb, 0x40, 0x92, 0x1a, 0xfa, 0xac, 0xe4, 0xe1, 0x71, 0x1f, 0x65, 0x8d, + 0x97, 0x9e, 0x95, 0x90, 0x5d, 0xb7, 0xc1, 0xaf, 0x54, 0xfb, 0x02, 0xe0, 0x35, 0xbb, 0x3a, 0x4d, + 0xad, 0x2c, 0x3d, 0x56, 0x08, 0x1b, 0x4a, 0x93, 0x6a, 0xab, 0xb8, 0x7a, 0xf2, 0x7d, 0xda, 0x3f, + 0xfe, 0x3e, 0xbe, 0xea, 0xaa, 0x44, 0xc6, 0xd0, 0x36, 0x48, 0x70, 0x96, 0x77, 0x24, 0x53, 0xdf, + 0xf3, 0x83, 0x28, 0x32, 0x45, 0x1e, 0xa4, 0xd3, 0xa2, 0x46, 0x6e, 0x9c, 0xdd, 0x63, 0xd4, 0x9d +} +}; + diff --git a/tables.h b/tables.h new file mode 100644 index 0000000..40b42d6 --- /dev/null +++ b/tables.h @@ -0,0 +1,21 @@ +/* + +Header file for S-boxes and MDS-matrices for the reference implementation of the Kalyna block cipher (DSTU 7624:2014) + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#ifndef KALYNA_TABLES_H +#define KALYNA_TABLES_H + +#include "kalyna.h" + +extern uint8_t mds_matrix[8][8]; +extern uint8_t mds_inv_matrix[8][8]; + +extern uint8_t sboxes_enc[4][256]; +extern uint8_t sboxes_dec[4][256]; + +#endif /* KALYNA_TABLES_H */ + diff --git a/transformations.h b/transformations.h new file mode 100644 index 0000000..bfb2fd3 --- /dev/null +++ b/transformations.h @@ -0,0 +1,324 @@ +/* + +Constant and basic transformations for the reference implementation of the Kalyna block cipher (DSTU 7624:2014) + +Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov + +*/ + +#ifndef KALYNA_DEFS_H +#define KALYNA_DEFS_H + + +#include +#include +#include +#include + +#include "kalyna.h" + + +#if (ULLONG_MAX != 0xFFFFFFFFFFFFFFFFULL) +#error "Architecture not supported. Required type to fit 64 bits." +#endif + +#define kBITS_IN_WORD 64 + +#if (CHAR_BIT != 8) +#error "Architecture not supported. Required type to fit 8 bits." +#endif + +#define kBITS_IN_BYTE 8 + +#define TRUE 1 +#define FALSE 0 + +/* Block words size. */ +#define kNB_128 2 +#define kNB_256 4 +#define kNB_512 8 + +/* Key words size. */ +#define kNK_128 2 +#define kNK_256 4 +#define kNK_512 8 + +/* Block bits size. */ +#define kBLOCK_128 kNB_128 * kBITS_IN_WORD +#define kBLOCK_256 kNB_256 * kBITS_IN_WORD +#define kBLOCK_512 kNB_512 * kBITS_IN_WORD + +/* Block bits size. */ +#define kKEY_128 kNK_128 * kBITS_IN_WORD +#define kKEY_256 kNK_256 * kBITS_IN_WORD +#define kKEY_512 kNK_512 * kBITS_IN_WORD + +/* Number of enciphering rounds size depending on key length. */ +#define kNR_128 10 +#define kNR_256 14 +#define kNR_512 18 + +#define kREDUCTION_POLYNOMIAL 0x011d /* x^8 + x^4 + x^3 + x^2 + 1 */ + +/*! + * Index a byte array as cipher state matrix. + */ +#define INDEX(table, row, col) table[(row) + (col) * sizeof(uint64_t)] + + +/*! + * Substitute each byte of the cipher state using corresponding S-Boxes. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void SubBytes(kalyna_t* ctx); + +/*! + * Inverse SubBytes transformation. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void InvSubBytes(kalyna_t* ctx); + +/*! + * Shift cipher state rows according to specification. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void ShiftRows(kalyna_t* ctx); + +/*! + * Inverse ShiftRows transformation. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void InvShiftRows(kalyna_t* ctx); + +/*! + * Multiply bytes in Finite Field GF(2^8). + * + * @param x Multiplicand element of GF(2^8). + * @param y Multiplier element of GF(2^8) from MDS matrix. + * @return Product of multiplication in GF(2^8). + */ +uint8_t MultiplyGF(uint8_t x, uint8_t y); + + +/*! + * Multiply cipher state by specified MDS matrix. + * Used to avoid code repetition for MixColumn and Inverse MixColumn. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param matrix MDS 8x8 byte matrix. + */ +void MatrixMultiply(kalyna_t* ctx, uint8_t matrix[8][8]); + +/*! + * Perform MixColumn transformation to the cipher state. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void MixColumns(kalyna_t* ctx); + +/*! + * Inverse MixColumn transformation. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void InvMixColumns(kalyna_t* ctx); + +/*! + * Perform single round enciphering routine. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void EncipherRound(kalyna_t* ctx); + +/*! + * Perform single round deciphering routine. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void DecipherRound(kalyna_t* ctx); + + +/*! + * Inject round key into the state using addition modulo 2^{64}. + * + * @param round Number of the round on which the key addition is performed in + * order to use the correct round key. + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void AddRoundKey(int round, kalyna_t* ctx); + +/*! + * Extract round key from the state using subtraction modulo 2^{64}. + * + * @param round Number of the round on which the key subtraction is performed + * in order to use the correct round key. + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void SubRoundKey(int round, kalyna_t* ctx); + +/*! + * Perform addition of two arbitrary states modulo 2^{64}. + * The operation is identical to simple round key addition but on arbitrary + * state array and addition value (instead of the actual round key). Used in + * key expansion procedure. The result is stored in `state`. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param value Is to be added to the state array modulo 2^{64}. + */ +void AddRoundKeyExpand(uint64_t* value, kalyna_t* ctx); + +/*! + * Inject round key into the state using XOR operation. + * + * @param round Number of the round on which the key addition is performed in + * order to use the correct round key. + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + */ +void XorRoundKey(int round, kalyna_t* ctx); + +/*! + * Perform XOR of two arbitrary states. + * The operation is identical to simple round key XORing but on arbitrary + * state array and addition value (instead of the actual round key). Used in + * key expansion procedure. The result is stored in `state`. + * XOR operation is involutive so no inverse transformation is required. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param value Is to be added to the state array modulo 2^{64}. + */ +void XorRoundKeyExpand(uint64_t* value, kalyna_t* ctx); + +/*! + * Rotate words of a state. + * The state is processed as 64-bit words array {w_{0}, w_{1}, ..., w_{nk-1}} + * and rotation is performed so the resulting state is + * {w_{1}, ..., w_{nk-1}, w_{0}}. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param state_value A state represented by 64-bit words array of length Nk. + * It is not the cipher state that is used during enciphering. + */ +void Rotate(size_t state_size, uint64_t* state_value); + +/*! + * Shift each word one bit to the left. + * The shift of each word is independent of other array words. + * + * @param state_size Size of the state to be shifted. + * @param state_value State represented as 64-bit words array. Note that this + * state Nk words long and differs from the cipher state used during + * enciphering. + */ +void ShiftLeft(size_t state_size, uint64_t* state_value); + +/*! + * Rotate the state (2 * Nb + 3) bytes to the left. + * The state is interpreted as bytes string in little endian. Big endian + * architectures are also correctly processed by this function. + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param state_value A state represented by 64-bit words array of length Nk. + * It is not the cipher state that is used during enciphering. + */ +void RotateLeft(size_t state_size, uint64_t* state_value); + +/*! + * Generate the Kt value (auxiliary key used in key expansion). + * + * @param ctx Initialized cipher context with current state and round keys + * precomputed. + * @param key Enciphering key of size corresponding to the one stored in cipher + * context `ctx` (specified via KalynaInit() function). + * @param kt Array for storing generated Kt value. + */ +void KeyExpandKt(uint64_t* key, kalyna_t* ctx, uint64_t* kt); + + +/*! + * Compute even round keys and store them in cipher context `ctx`. + * + * @param key Kalyna enciphering key of length Nk 64-bit words. + * @param kt Kalyna auxiliary key. The size is equal to enciphering state + * size and equals Nb 64-bit words. + * @param ctx Initialized cipher context. + */ +void KeyExpandEven(uint64_t* key, uint64_t* kt, kalyna_t* ctx); + +/*! + * Compute odd round keys by rotating already generated even ones and + * fill in the rest of the round keys in cipher context `ctx`. + * + * @param ctx Initialized cipher context. + */ +void KeyExpandOdd(kalyna_t* ctx); + +/*! + * Convert array of 64-bit words to array of bytes. + * Each word is interpreted as byte sequence following little endian + * convention. However a check for big endian and corresponding word reversion + * is performed if needed. + * + * @param length Length of 64-bit words array. + * @param words Pointer to 64-bit words array. + * @return Pointer to bytes array. + */ +uint8_t* WordsToBytes(size_t length, uint64_t* words); + +/*! + * Convert array of bytes to array of 64-bit words. + * Each word is interpreted as byte sequence following little endian + * convention. However a check for big endian and corresponding word reversion + * is performed if needed. + * + * @param length Length of bytes array. + * @param words Pointer to bytes array. + * @return Pointer to 64-bit words array. + */ +uint64_t* BytesToWords(size_t length, uint8_t* bytes); + +/*! + * Reverse bytes ordering that form the word. + * + * @param word 64-bit word that needs its bytes to be reversed (perhaps for + * converting between little and big endian). + * @return 64-bit word with reversed bytes. + */ +uint64_t ReverseWord(uint64_t word); + +/*! + * Check if architecture follows big endian convention. + * + * @return 1 if architecture is big endian, 0 if it is little endian. + */ +int IsBigEndian(); + +/*! + * Print specified cipher state (or any similar array) to stdout. + * + * @param length Length of the words array. + * @param state State represented as words array. + */ +void PrintState(size_t length, uint64_t* state); + +#endif /* KALYNA_DEFS_H */ + -- 2.11.0