Adding reference implementation
[kalyna-python] / transformations.h
1 /*
2
3 Constant and basic transformations for the reference implementation of the Kalyna block cipher (DSTU 7624:2014)
4
5 Authors: Ruslan Kiianchuk, Ruslan Mordvinov, Roman Oliynykov
6
7 */
8
9 #ifndef KALYNA_DEFS_H
10 #define KALYNA_DEFS_H
11
12
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <memory.h>
16 #include <limits.h>
17
18 #include "kalyna.h"
19
20
21 #if (ULLONG_MAX != 0xFFFFFFFFFFFFFFFFULL)
22 #error "Architecture not supported. Required type to fit 64 bits."
23 #endif
24
25 #define kBITS_IN_WORD 64
26
27 #if (CHAR_BIT != 8)
28 #error "Architecture not supported. Required type to fit 8 bits."
29 #endif
30
31 #define kBITS_IN_BYTE 8
32
33 #define TRUE 1
34 #define FALSE 0
35
36 /* Block words size. */
37 #define kNB_128 2
38 #define kNB_256 4
39 #define kNB_512 8
40
41 /* Key words size. */
42 #define kNK_128 2
43 #define kNK_256 4
44 #define kNK_512 8
45
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
50
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
55
56 /* Number of enciphering rounds size depending on key length. */
57 #define kNR_128 10
58 #define kNR_256 14
59 #define kNR_512 18
60
61 #define kREDUCTION_POLYNOMIAL 0x011d /* x^8 + x^4 + x^3 + x^2 + 1 */
62
63 /*!
64 * Index a byte array as cipher state matrix.
65 */
66 #define INDEX(table, row, col) table[(row) + (col) * sizeof(uint64_t)]
67
68
69 /*!
70 * Substitute each byte of the cipher state using corresponding S-Boxes.
71 *
72 * @param ctx Initialized cipher context with current state and round keys
73 * precomputed.
74 */
75 void SubBytes(kalyna_t* ctx);
76
77 /*!
78 * Inverse SubBytes transformation.
79 *
80 * @param ctx Initialized cipher context with current state and round keys
81 * precomputed.
82 */
83 void InvSubBytes(kalyna_t* ctx);
84
85 /*!
86 * Shift cipher state rows according to specification.
87 *
88 * @param ctx Initialized cipher context with current state and round keys
89 * precomputed.
90 */
91 void ShiftRows(kalyna_t* ctx);
92
93 /*!
94 * Inverse ShiftRows transformation.
95 *
96 * @param ctx Initialized cipher context with current state and round keys
97 * precomputed.
98 */
99 void InvShiftRows(kalyna_t* ctx);
100
101 /*!
102 * Multiply bytes in Finite Field GF(2^8).
103 *
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).
107 */
108 uint8_t MultiplyGF(uint8_t x, uint8_t y);
109
110
111 /*!
112 * Multiply cipher state by specified MDS matrix.
113 * Used to avoid code repetition for MixColumn and Inverse MixColumn.
114 *
115 * @param ctx Initialized cipher context with current state and round keys
116 * precomputed.
117 * @param matrix MDS 8x8 byte matrix.
118 */
119 void MatrixMultiply(kalyna_t* ctx, uint8_t matrix[8][8]);
120
121 /*!
122 * Perform MixColumn transformation to the cipher state.
123 *
124 * @param ctx Initialized cipher context with current state and round keys
125 * precomputed.
126 */
127 void MixColumns(kalyna_t* ctx);
128
129 /*!
130 * Inverse MixColumn transformation.
131 *
132 * @param ctx Initialized cipher context with current state and round keys
133 * precomputed.
134 */
135 void InvMixColumns(kalyna_t* ctx);
136
137 /*!
138 * Perform single round enciphering routine.
139 *
140 * @param ctx Initialized cipher context with current state and round keys
141 * precomputed.
142 */
143 void EncipherRound(kalyna_t* ctx);
144
145 /*!
146 * Perform single round deciphering routine.
147 *
148 * @param ctx Initialized cipher context with current state and round keys
149 * precomputed.
150 */
151 void DecipherRound(kalyna_t* ctx);
152
153
154 /*!
155 * Inject round key into the state using addition modulo 2^{64}.
156 *
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
160 * precomputed.
161 */
162 void AddRoundKey(int round, kalyna_t* ctx);
163
164 /*!
165 * Extract round key from the state using subtraction modulo 2^{64}.
166 *
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
170 * precomputed.
171 */
172 void SubRoundKey(int round, kalyna_t* ctx);
173
174 /*!
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`.
179 *
180 * @param ctx Initialized cipher context with current state and round keys
181 * precomputed.
182 * @param value Is to be added to the state array modulo 2^{64}.
183 */
184 void AddRoundKeyExpand(uint64_t* value, kalyna_t* ctx);
185
186 /*!
187 * Inject round key into the state using XOR operation.
188 *
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
192 * precomputed.
193 */
194 void XorRoundKey(int round, kalyna_t* ctx);
195
196 /*!
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.
202 *
203 * @param ctx Initialized cipher context with current state and round keys
204 * precomputed.
205 * @param value Is to be added to the state array modulo 2^{64}.
206 */
207 void XorRoundKeyExpand(uint64_t* value, kalyna_t* ctx);
208
209 /*!
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}}.
214 *
215 * @param ctx Initialized cipher context with current state and round keys
216 * precomputed.
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.
219 */
220 void Rotate(size_t state_size, uint64_t* state_value);
221
222 /*!
223 * Shift each word one bit to the left.
224 * The shift of each word is independent of other array words.
225 *
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
229 * enciphering.
230 */
231 void ShiftLeft(size_t state_size, uint64_t* state_value);
232
233 /*!
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.
237 *
238 * @param ctx Initialized cipher context with current state and round keys
239 * precomputed.
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.
242 */
243 void RotateLeft(size_t state_size, uint64_t* state_value);
244
245 /*!
246 * Generate the Kt value (auxiliary key used in key expansion).
247 *
248 * @param ctx Initialized cipher context with current state and round keys
249 * precomputed.
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.
253 */
254 void KeyExpandKt(uint64_t* key, kalyna_t* ctx, uint64_t* kt);
255
256
257 /*!
258 * Compute even round keys and store them in cipher context `ctx`.
259 *
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.
264 */
265 void KeyExpandEven(uint64_t* key, uint64_t* kt, kalyna_t* ctx);
266
267 /*!
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`.
270 *
271 * @param ctx Initialized cipher context.
272 */
273 void KeyExpandOdd(kalyna_t* ctx);
274
275 /*!
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.
280 *
281 * @param length Length of 64-bit words array.
282 * @param words Pointer to 64-bit words array.
283 * @return Pointer to bytes array.
284 */
285 uint8_t* WordsToBytes(size_t length, uint64_t* words);
286
287 /*!
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.
292 *
293 * @param length Length of bytes array.
294 * @param words Pointer to bytes array.
295 * @return Pointer to 64-bit words array.
296 */
297 uint64_t* BytesToWords(size_t length, uint8_t* bytes);
298
299 /*!
300 * Reverse bytes ordering that form the word.
301 *
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.
305 */
306 uint64_t ReverseWord(uint64_t word);
307
308 /*!
309 * Check if architecture follows big endian convention.
310 *
311 * @return 1 if architecture is big endian, 0 if it is little endian.
312 */
313 int IsBigEndian();
314
315 /*!
316 * Print specified cipher state (or any similar array) to stdout.
317 *
318 * @param length Length of the words array.
319 * @param state State represented as words array.
320 */
321 void PrintState(size_t length, uint64_t* state);
322
323 #endif /* KALYNA_DEFS_H */
324