3 Constant and basic transformations for the reference implementation of the Kalyna block cipher (DSTU 7624:2014)
5 Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov
21 #if (ULLONG_MAX != 0xFFFFFFFFFFFFFFFFULL)
22 #error "Architecture not supported. Required type to fit 64 bits."
25 #define kBITS_IN_WORD 64
28 #error "Architecture not supported. Required type to fit 8 bits."
31 #define kBITS_IN_BYTE 8
36 /* Block words size. */
46 /* Block bits size. */
47 #define kBLOCK_128 kNB_128 * kBITS_IN_WORD
48 #define kBLOCK_256 kNB_256 * kBITS_IN_WORD
49 #define kBLOCK_512 kNB_512 * kBITS_IN_WORD
51 /* Block bits size. */
52 #define kKEY_128 kNK_128 * kBITS_IN_WORD
53 #define kKEY_256 kNK_256 * kBITS_IN_WORD
54 #define kKEY_512 kNK_512 * kBITS_IN_WORD
56 /* Number of enciphering rounds size depending on key length. */
61 #define kREDUCTION_POLYNOMIAL 0x011d /* x^8 + x^4 + x^3 + x^2 + 1 */
64 * Index a byte array as cipher state matrix.
66 #define INDEX(table, row, col) table[(row) + (col) * sizeof(uint64_t)]
70 * Substitute each byte of the cipher state using corresponding S-Boxes.
72 * @param ctx Initialized cipher context with current state and round keys
75 void SubBytes(kalyna_t* ctx);
78 * Inverse SubBytes transformation.
80 * @param ctx Initialized cipher context with current state and round keys
83 void InvSubBytes(kalyna_t* ctx);
86 * Shift cipher state rows according to specification.
88 * @param ctx Initialized cipher context with current state and round keys
91 void ShiftRows(kalyna_t* ctx);
94 * Inverse ShiftRows transformation.
96 * @param ctx Initialized cipher context with current state and round keys
99 void InvShiftRows(kalyna_t* ctx);
102 * Multiply bytes in Finite Field GF(2^8).
104 * @param x Multiplicand element of GF(2^8).
105 * @param y Multiplier element of GF(2^8) from MDS matrix.
106 * @return Product of multiplication in GF(2^8).
108 uint8_t MultiplyGF(uint8_t x, uint8_t y);
112 * Multiply cipher state by specified MDS matrix.
113 * Used to avoid code repetition for MixColumn and Inverse MixColumn.
115 * @param ctx Initialized cipher context with current state and round keys
117 * @param matrix MDS 8x8 byte matrix.
119 void MatrixMultiply(kalyna_t* ctx, uint8_t matrix[8][8]);
122 * Perform MixColumn transformation to the cipher state.
124 * @param ctx Initialized cipher context with current state and round keys
127 void MixColumns(kalyna_t* ctx);
130 * Inverse MixColumn transformation.
132 * @param ctx Initialized cipher context with current state and round keys
135 void InvMixColumns(kalyna_t* ctx);
138 * Perform single round enciphering routine.
140 * @param ctx Initialized cipher context with current state and round keys
143 void EncipherRound(kalyna_t* ctx);
146 * Perform single round deciphering routine.
148 * @param ctx Initialized cipher context with current state and round keys
151 void DecipherRound(kalyna_t* ctx);
155 * Inject round key into the state using addition modulo 2^{64}.
157 * @param round Number of the round on which the key addition is performed in
158 * order to use the correct round key.
159 * @param ctx Initialized cipher context with current state and round keys
162 void AddRoundKey(int round, kalyna_t* ctx);
165 * Extract round key from the state using subtraction modulo 2^{64}.
167 * @param round Number of the round on which the key subtraction is performed
168 * in order to use the correct round key.
169 * @param ctx Initialized cipher context with current state and round keys
172 void SubRoundKey(int round, kalyna_t* ctx);
175 * Perform addition of two arbitrary states modulo 2^{64}.
176 * The operation is identical to simple round key addition but on arbitrary
177 * state array and addition value (instead of the actual round key). Used in
178 * key expansion procedure. The result is stored in `state`.
180 * @param ctx Initialized cipher context with current state and round keys
182 * @param value Is to be added to the state array modulo 2^{64}.
184 void AddRoundKeyExpand(uint64_t* value, kalyna_t* ctx);
187 * Inject round key into the state using XOR operation.
189 * @param round Number of the round on which the key addition is performed in
190 * order to use the correct round key.
191 * @param ctx Initialized cipher context with current state and round keys
194 void XorRoundKey(int round, kalyna_t* ctx);
197 * Perform XOR of two arbitrary states.
198 * The operation is identical to simple round key XORing but on arbitrary
199 * state array and addition value (instead of the actual round key). Used in
200 * key expansion procedure. The result is stored in `state`.
201 * XOR operation is involutive so no inverse transformation is required.
203 * @param ctx Initialized cipher context with current state and round keys
205 * @param value Is to be added to the state array modulo 2^{64}.
207 void XorRoundKeyExpand(uint64_t* value, kalyna_t* ctx);
210 * Rotate words of a state.
211 * The state is processed as 64-bit words array {w_{0}, w_{1}, ..., w_{nk-1}}
212 * and rotation is performed so the resulting state is
213 * {w_{1}, ..., w_{nk-1}, w_{0}}.
215 * @param ctx Initialized cipher context with current state and round keys
217 * @param state_value A state represented by 64-bit words array of length Nk.
218 * It is not the cipher state that is used during enciphering.
220 void Rotate(size_t state_size, uint64_t* state_value);
223 * Shift each word one bit to the left.
224 * The shift of each word is independent of other array words.
226 * @param state_size Size of the state to be shifted.
227 * @param state_value State represented as 64-bit words array. Note that this
228 * state Nk words long and differs from the cipher state used during
231 void ShiftLeft(size_t state_size, uint64_t* state_value);
234 * Rotate the state (2 * Nb + 3) bytes to the left.
235 * The state is interpreted as bytes string in little endian. Big endian
236 * architectures are also correctly processed by this function.
238 * @param ctx Initialized cipher context with current state and round keys
240 * @param state_value A state represented by 64-bit words array of length Nk.
241 * It is not the cipher state that is used during enciphering.
243 void RotateLeft(size_t state_size, uint64_t* state_value);
246 * Generate the Kt value (auxiliary key used in key expansion).
248 * @param ctx Initialized cipher context with current state and round keys
250 * @param key Enciphering key of size corresponding to the one stored in cipher
251 * context `ctx` (specified via KalynaInit() function).
252 * @param kt Array for storing generated Kt value.
254 void KeyExpandKt(uint64_t* key, kalyna_t* ctx, uint64_t* kt);
258 * Compute even round keys and store them in cipher context `ctx`.
260 * @param key Kalyna enciphering key of length Nk 64-bit words.
261 * @param kt Kalyna auxiliary key. The size is equal to enciphering state
262 * size and equals Nb 64-bit words.
263 * @param ctx Initialized cipher context.
265 void KeyExpandEven(uint64_t* key, uint64_t* kt, kalyna_t* ctx);
268 * Compute odd round keys by rotating already generated even ones and
269 * fill in the rest of the round keys in cipher context `ctx`.
271 * @param ctx Initialized cipher context.
273 void KeyExpandOdd(kalyna_t* ctx);
276 * Convert array of 64-bit words to array of bytes.
277 * Each word is interpreted as byte sequence following little endian
278 * convention. However a check for big endian and corresponding word reversion
279 * is performed if needed.
281 * @param length Length of 64-bit words array.
282 * @param words Pointer to 64-bit words array.
283 * @return Pointer to bytes array.
285 uint8_t* WordsToBytes(size_t length, uint64_t* words);
288 * Convert array of bytes to array of 64-bit words.
289 * Each word is interpreted as byte sequence following little endian
290 * convention. However a check for big endian and corresponding word reversion
291 * is performed if needed.
293 * @param length Length of bytes array.
294 * @param words Pointer to bytes array.
295 * @return Pointer to 64-bit words array.
297 uint64_t* BytesToWords(size_t length, uint8_t* bytes);
300 * Reverse bytes ordering that form the word.
302 * @param word 64-bit word that needs its bytes to be reversed (perhaps for
303 * converting between little and big endian).
304 * @return 64-bit word with reversed bytes.
306 uint64_t ReverseWord(uint64_t word);
309 * Check if architecture follows big endian convention.
311 * @return 1 if architecture is big endian, 0 if it is little endian.
316 * Print specified cipher state (or any similar array) to stdout.
318 * @param length Length of the words array.
319 * @param state State represented as words array.
321 void PrintState(size_t length, uint64_t* state);
323 #endif /* KALYNA_DEFS_H */