Commit | Line | Data |
---|---|---|
22eafbca RO |
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 | */ | |
0a501374 | 313 | int IsBigEndian(void); |
22eafbca RO |
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 |