Adding reference implementation
authorRoman Oliynykov <roliynykov@gmail.com>
Wed, 15 Jul 2015 16:30:00 +0000 (19:30 +0300)
committerRoman Oliynykov <roliynykov@gmail.com>
Wed, 15 Jul 2015 16:30:00 +0000 (19:30 +0300)
kalyna.c [new file with mode: 0644]
kalyna.h [new file with mode: 0644]
main.c [new file with mode: 0644]
makefile [new file with mode: 0644]
tables.c [new file with mode: 0644]
tables.h [new file with mode: 0644]
transformations.h [new file with mode: 0644]

diff --git a/kalyna.c b/kalyna.c
new file mode 100644 (file)
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 (file)
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 <stdlib.h>
+#include <string.h>
+
+
+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 (file)
index 0000000..618a0a7
--- /dev/null
+++ b/main.c
@@ -0,0 +1,326 @@
+/*\r
+\r
+main.c, printing test vectors of reference implementation of the Kalyna block cipher (DSTU 7624:2014), all block and key length variants\r
+\r
+Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov\r
+\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <memory.h>\r
+\r
+#include "kalyna.h"\r
+#include "transformations.h"\r
+\r
+void print (int data_size, uint64_t data []);\r
+\r
+int main(int argc, char** argv) {\r
+   \r
+       int i;\r
+       kalyna_t* ctx22_e = KalynaInit(128, 128);\r
+       kalyna_t* ctx24_e = KalynaInit(128, 256);\r
+       kalyna_t* ctx44_e = KalynaInit(256, 256);\r
+       kalyna_t* ctx48_e = KalynaInit(256, 512);\r
+       kalyna_t* ctx88_e = KalynaInit(512, 512);\r
+\r
+    uint64_t pt22_e[2] = {0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL};\r
+       uint64_t ct22_e[2];\r
+    uint64_t key22_e[2] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL};\r
+    uint64_t expect22_e[2] = {0x20ac9b777d1cbf81ULL, 0x06add2b439eac9e1ULL};\r
+\r
+    uint64_t pt24_e[2] = {0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL};\r
+       uint64_t ct24_e[2];\r
+    uint64_t key24_e[4] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL};\r
+    uint64_t expect24_e[2] = { 0x8a150010093eec58ULL, 0x144f336f16f74811ULL};\r
+\r
+    uint64_t pt44_e[4] = {0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL};\r
+       uint64_t ct44_e[4];\r
+    uint64_t key44_e[4] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL};\r
+    uint64_t expect44_e[4] = {0x3521c90e573d6ef6ULL, 0x8c2abddc23e3daaeULL, 0x5a0d6a20ec6339a0ULL, 0x2cd97f61245c3888ULL};\r
+\r
+    uint64_t pt48_e[4] = {0x4746454443424140ULL, 0x4f4e4d4c4b4a4948ULL, 0x5756555453525150ULL, 0x5f5e5d5c5b5a5958ULL};\r
+       uint64_t ct48_e[4];\r
+    uint64_t key48_e[8] = {0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL,\r
+                                                       0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL};\r
+    uint64_t expect48_e[4] = {0x7ab6b7e6e9906960ULL, 0xb76822d793d8d64bULL, 0x02e1d73c3cc8028eULL, 0xd95dfefda8742efdULL};\r
+\r
+\r
+    uint64_t pt88_e[8] = {  0x4746454443424140ULL, 0x4f4e4d4c4b4a4948ULL, 0x5756555453525150ULL, 0x5f5e5d5c5b5a5958ULL,\r
+                                                                       0x6766656463626160ULL, 0x6f6e6d6c6b6a6968ULL, 0x7776757473727170ULL, 0x7f7e7d7c7b7a7978ULL};\r
+       uint64_t ct88_e[8];\r
+    uint64_t key88_e[8] = {            0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL,\r
+                                                                       0x2726252423222120ULL, 0x2f2e2d2c2b2a2928ULL, 0x3736353433323130ULL, 0x3f3e3d3c3b3a3938ULL};\r
+    uint64_t expect88_e[8] = {     0x6a351c811be3264aULL, 0x1a239605cad61da6ULL, 0xa1f347aa5483ba67ULL, 0xb856eb20c3ee1d3eULL,\r
+                                                                       0x66ab5b1717f4d095ULL, 0x6cc815bb34f1d62fULL, 0xb7fe6e85266a90cbULL, 0xd9d90d947264bcc5ULL};\r
+\r
+       uint64_t ct22_d[2] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL};\r
+       uint64_t pt22_d[2];\r
+    uint64_t key22_d[2] = {0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL};\r
+    uint64_t expect22_d[2] = {0x84c70c472bef9172ULL, 0xd7da733930c2096fULL};\r
+\r
+       uint64_t ct24_d[2] = {0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL};\r
+       uint64_t pt24_d[2];\r
+    uint64_t key24_d[4] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL};\r
+    uint64_t expect24_d[2] = {0xe1dffdce56b46df3ULL, 0x96d9ca30705f5bb4ULL};\r
+\r
+       uint64_t ct44_d[4] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL};\r
+       uint64_t pt44_d[4];\r
+    uint64_t key44_d[4] = {0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL};\r
+    uint64_t expect44_d[4] = {0x864e67967823c57fULL, 0xa34b8b3fb0e9c103ULL, 0xd3c33f2c597c5babULL, 0xe30fb28625d1ed61ULL};\r
+\r
+       uint64_t ct48_d[4] = {0x58595a5b5c5d5e5fULL, 0x5051525354555657ULL, 0x48494a4b4c4d4e4fULL, 0x4041424344454647ULL};\r
+       uint64_t pt48_d[4];\r
+    uint64_t key48_d[8] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL,\r
+                                               0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL};\r
+    uint64_t expect48_d[4] = {0x82d4da67277a3118ULL, 0x078d78a1b907cdbcULL, 0x97845f9e1898705eULL, 0xe06aba796d910b2dULL};\r
+\r
+       uint64_t ct88_d[8] = {0x78797a7b7c7d7e7fULL, 0x7071727374757677ULL, 0x68696a6b6c6d6e6fULL, 0x6061626364656667ULL,\r
+                                               0x58595a5b5c5d5e5fULL, 0x5051525354555657ULL, 0x48494a4b4c4d4e4fULL, 0x4041424344454647ULL};\r
+       uint64_t pt88_d[8];\r
+    uint64_t key88_d[8] = {0x38393a3b3c3d3e3fULL, 0x3031323334353637ULL, 0x28292a2b2c2d2e2fULL, 0x2021222324252627ULL,\r
+                                               0x18191a1b1c1d1e1fULL, 0x1011121314151617ULL, 0x08090a0b0c0d0e0fULL, 0x0001020304050607ULL};\r
+    uint64_t expect88_d[8] = {0x5252a025338480ceULL, 0x29d8a9e614d7ea1bULL, 0xbd45a8e90e1e38fdULL, 0xa346fad954450492ULL,\r
+                                               0xf2b13b85dbef7f75ULL, 0x6ae6753b839dff97ULL, 0xdc1b29b5ab5741afULL, 0x22ff5aaa13bb94f0ULL };\r
+\r
+       kalyna_t* ctx22_d = KalynaInit(128, 128);\r
+       kalyna_t* ctx24_d = KalynaInit(128, 256);\r
+       kalyna_t* ctx44_d = KalynaInit(256, 256);\r
+       kalyna_t* ctx48_d = KalynaInit(256, 512);\r
+       kalyna_t* ctx88_d = KalynaInit(512, 512);\r
+\r
+       // kalyna 22 enc\r
+       KalynaKeyExpand(key22_e, ctx22_e);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx22_e->nb * 64, ctx22_e->nk * 64);\r
+   \r
+       printf("\n--- ENCIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx22_e->nk, key22_e);\r
+\r
+    printf("Plaintext:\n");\r
+    print(ctx22_e->nb, pt22_e);\r
+\r
+    KalynaEncipher(pt22_e, ctx22_e, ct22_e);\r
+    printf("Ciphertext:\n");\r
+    print(ctx22_e->nb, ct22_e);\r
+\r
+       if (memcmp(ct22_e, expect22_e, sizeof(ct22_e)) != 0) printf("Failed enciphering\n");\r
+       else printf("Success enciphering\n\n");\r
+\r
+       KalynaDelete(ctx22_e);\r
+\r
+       // kalyna 22 dec\r
+       KalynaKeyExpand(key22_d, ctx22_d);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx22_d->nb * 64, ctx22_d->nk * 64);\r
+   \r
+       printf("\n--- DECIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx22_d->nk, key22_d);\r
+\r
+       printf("Ciphertext:\n");\r
+    print(ctx22_d->nb, ct22_d);\r
+\r
+       KalynaDecipher(ct22_d, ctx22_d, pt22_d);\r
+    printf("Plaintext:\n");\r
+    print(ctx22_d->nb, pt22_d);\r
+\r
+       if (memcmp(pt22_d, expect22_d, sizeof(pt22_d)) != 0) printf("Failed deciphering\n");\r
+       else printf("Success deciphering\n\n");\r
+\r
+       KalynaDelete(ctx22_d);\r
+       \r
+       // kalyna 24 enc\r
+       KalynaKeyExpand(key24_e, ctx24_e);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx24_e->nb * 64, ctx24_e->nk * 64);\r
+\r
+    printf("\n--- ENCIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx24_e->nk, key24_e);\r
+\r
+    printf("Plaintext:\n");\r
+    print(ctx24_e->nb, pt24_e);\r
+\r
+    KalynaEncipher(pt24_e, ctx24_e, ct24_e);\r
+    printf("Ciphertext:\n");\r
+    print(ctx24_e->nb, ct24_e);\r
+\r
+       if (memcmp(ct24_e, expect24_e, sizeof(ct24_e)) != 0) printf("Failed enciphering\n");\r
+       else printf("Success enciphering\n\n");\r
+\r
+       KalynaDelete(ctx24_e);\r
+\r
+       // kalyna 24 dec\r
+       KalynaKeyExpand(key24_d, ctx24_d);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx24_d->nb * 64, ctx24_d->nk * 64);\r
+   \r
+       printf("\n--- DECIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx24_d->nk, key24_d);\r
+\r
+       printf("Ciphertext:\n");\r
+    print(ctx24_d->nb, ct24_d);\r
+\r
+       KalynaDecipher(ct24_d, ctx24_d, pt24_d);\r
+    printf("Plaintext:\n");\r
+    print(ctx24_d->nb, pt24_d);\r
+\r
+       if (memcmp(pt24_d, expect24_d, sizeof(pt24_d)) != 0) printf("Failed deciphering\n");\r
+       else printf("Success deciphering\n\n");\r
+\r
+       KalynaDelete(ctx24_d);\r
+\r
+       // kalyna 44 enc\r
+       KalynaKeyExpand(key44_e, ctx44_e);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx44_e->nb * 64, ctx44_e->nk * 64);\r
+\r
+    printf("\n--- ENCIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx44_e->nk, key44_e);\r
+\r
+    printf("Plaintext:\n");\r
+    print(ctx44_e->nb, pt44_e);\r
+\r
+    KalynaEncipher(pt44_e, ctx44_e, ct44_e);\r
+    printf("Ciphertext:\n");\r
+    print(ctx44_e->nb, ct44_e);\r
+\r
+       if (memcmp(ct44_e, expect44_e, sizeof(ct44_e)) != 0) printf("Failed enciphering\n");\r
+       else printf("Success enciphering\n\n");\r
+\r
+       KalynaDelete(ctx44_e);\r
+\r
+       // kalyna 44 dec\r
+       KalynaKeyExpand(key44_d, ctx44_d);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx44_d->nb * 64, ctx44_d->nk * 64);\r
+   \r
+       printf("\n--- DECIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx44_d->nk, key44_d);\r
+\r
+       printf("Ciphertext:\n");\r
+    print(ctx44_d->nb, ct44_d);\r
+\r
+       KalynaDecipher(ct44_d, ctx44_d, pt44_d);\r
+    printf("Plaintext:\n");\r
+    print(ctx44_d->nb, pt44_d);\r
+\r
+       if (memcmp(pt44_d, expect44_d, sizeof(pt44_d)) != 0) printf("Failed deciphering\n");\r
+       else printf("Success deciphering\n\n");\r
+\r
+       KalynaDelete(ctx44_d);\r
+\r
+       // kalyna 48 enc\r
+       KalynaKeyExpand(key48_e, ctx48_e);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx48_e->nb * 64, ctx48_e->nk * 64);\r
+   \r
+    printf("\n--- ENCIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx48_e->nk, key48_e);\r
+\r
+    printf("Plaintext:\n");\r
+    print(ctx48_e->nb, pt48_e);\r
+\r
+    KalynaEncipher(pt48_e, ctx48_e, ct48_e);\r
+    printf("Ciphertext:\n");\r
+    print(ctx48_e->nb, ct48_e);\r
+\r
+       if (memcmp(ct48_e, expect48_e, sizeof(ct48_e)) != 0) printf("Failed enciphering\n");\r
+       else printf("Success enciphering\n\n");\r
+\r
+       KalynaDelete(ctx48_e);\r
+\r
+       // kalyna 48 dec\r
+       KalynaKeyExpand(key48_d, ctx48_d);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx48_d->nb * 64, ctx48_d->nk * 64);\r
+   \r
+       printf("\n--- DECIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx48_d->nk, key48_d);\r
+\r
+       printf("Ciphertext:\n");\r
+    print(ctx48_d->nb, ct48_d);\r
+\r
+       KalynaDecipher(ct48_d, ctx48_d, pt48_d);\r
+    printf("Plaintext:\n");\r
+    print(ctx48_d->nb, pt48_d);\r
+\r
+       if (memcmp(pt48_d, expect48_d, sizeof(pt48_d)) != 0) printf("Failed deciphering\n");\r
+       else printf("Success deciphering\n\n");\r
+\r
+       KalynaDelete(ctx48_d);\r
+\r
+       // kalyna 88 enc\r
+       KalynaKeyExpand(key88_e, ctx88_e);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx88_e->nb * 64, ctx88_e->nk * 64);\r
+\r
+    printf("\n--- ENCIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx88_e->nk, key88_e);\r
+\r
+    printf("Plaintext:\n");\r
+    print(ctx88_e->nb, pt88_e);\r
+\r
+    KalynaEncipher(pt88_e, ctx88_e, ct88_e);\r
+    printf("Ciphertext:\n");\r
+    print(ctx88_e->nb, ct88_e);\r
+\r
+       if (memcmp(ct88_e, expect88_e, sizeof(ct88_e)) != 0) printf("Failed enciphering\n");\r
+       else printf("Success enciphering\n\n");\r
+\r
+       KalynaDelete(ctx88_e);\r
+\r
+       // kalyna 88 dec\r
+       KalynaKeyExpand(key88_d, ctx88_d);\r
+\r
+    printf("\n=============\n");\r
+    printf("Kalyna (%lu, %lu)\n", ctx88_d->nb * 64, ctx88_d->nk * 64);\r
+   \r
+       printf("\n--- DECIPHERING ---\n");\r
+    printf("Key:\n");\r
+    print(ctx88_d->nk, key88_d);\r
+\r
+       printf("Ciphertext:\n");\r
+    print(ctx88_d->nb, ct88_d);\r
+\r
+       KalynaDecipher(ct88_d, ctx88_d, pt88_d);\r
+    printf("Plaintext:\n");\r
+    print(ctx88_d->nb, pt88_d);\r
+\r
+       if (memcmp(pt88_d, expect88_d, sizeof(pt88_d)) != 0) printf("Failed deciphering\n");\r
+       else printf("Success deciphering\n\n");\r
+\r
+       KalynaDelete(ctx88_d);\r
+\r
+    return 0;\r
+}\r
+\r
+\r
+void print (int data_size, uint64_t data [])\r
+{\r
+       int i;\r
+       uint8_t * tmp = (uint8_t *) data; \r
+       for (i = 0; i < data_size * 8; i ++)\r
+       {\r
+               if (! (i % 16)) printf ("    ");\r
+               printf ("%02X", (unsigned int) tmp [i]);\r
+               if (!((i + 1) % 16)) printf ("\n");\r
+       };\r
+       printf ("\n");\r
+};\r
diff --git a/makefile b/makefile
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
index 0000000..bfb2fd3
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <limits.h>
+
+#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 */
+