--- /dev/null
+/*
+
+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");
+}
+
--- /dev/null
+/*\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
--- /dev/null
+/*
+
+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
+}
+};
+