1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implementation of GOST 28147-89 encryption algorithm *
7 * No OpenSSL libraries required to compile and use *
9 **********************************************************************/
11 #include <openssl/crypto.h>
14 Substitution blocks from RFC 4357
16 Note: our implementation of gost 28147-89 algorithm
17 uses S-box matrix rotated 90 degrees counterclockwise, relative to
18 examples given in RFC.
23 /* Substitution blocks from test examples for GOST R 34.11-94*/
24 gost_subst_block GostR3411_94_TestParamSet = {
25 {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB,
28 {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8,
31 {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC,
34 {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3,
37 {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2,
40 {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0,
43 {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7,
46 {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF,
50 /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
51 gost_subst_block GostR3411_94_CryptoProParamSet = {
52 {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0,
55 {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2,
58 {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE,
61 {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD,
64 {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB,
67 {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA,
70 {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE,
73 {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2,
77 /* Test paramset from GOST 28147 */
78 gost_subst_block Gost28147_TestParamSet = {
79 {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4,
82 {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA,
85 {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE,
88 {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1,
91 {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4,
94 {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF,
97 {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0,
100 {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7,
104 /* 1.2.643.2.2.31.1 */
105 gost_subst_block Gost28147_CryptoProParamSetA = {
106 {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7,
109 {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3,
112 {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF,
115 {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7,
118 {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8,
121 {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7,
124 {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4,
127 {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0,
131 /* 1.2.643.2.2.31.2 */
132 gost_subst_block Gost28147_CryptoProParamSetB = {
133 {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD,
136 {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF,
139 {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0,
142 {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8,
145 {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE,
148 {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6,
151 {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8,
154 {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6,
158 /* 1.2.643.2.2.31.3 */
159 gost_subst_block Gost28147_CryptoProParamSetC = {
160 {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9,
163 {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1,
166 {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0,
169 {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF,
172 {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF,
175 {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE,
178 {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA,
181 {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7,
185 /* 1.2.643.2.2.31.4 */
186 gost_subst_block Gost28147_CryptoProParamSetD = {
187 {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD,
190 {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA,
193 {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9,
196 {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE,
199 {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3,
202 {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3,
205 {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA,
208 {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB,
212 /* 1.2.643.7.1.2.5.1.1 */
213 gost_subst_block Gost28147_TC26ParamSetZ = {
214 {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc,
217 {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa,
220 {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3,
223 {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4,
226 {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe,
229 {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9,
232 {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd,
235 {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3,
239 const byte CryptoProKeyMeshingKey[] = {
240 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
241 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
242 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
243 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
246 const byte ACPKM_D_const[] = {
247 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
248 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
249 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
250 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
253 /* Initialization of gost_ctx subst blocks*/
254 void kboxinit(gost_ctx * c, const gost_subst_block * b)
258 for (i = 0; i < 256; i++) {
259 c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
260 c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
261 c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
262 c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
267 /* Part of GOST 28147 algorithm moved into separate function */
268 static word32 f(gost_ctx * c, word32 x)
270 x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
271 c->k43[x >> 8 & 255] | c->k21[x & 255];
272 /* Rotate left 11 bits */
273 return x << 11 | x >> (32 - 11);
276 /* Low-level encryption routine - encrypts one 64 bit block*/
277 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
279 register word32 n1, n2; /* As named in the GOST */
280 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
281 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
282 /* Instead of swapping halves, swap names each round */
284 n2 ^= f(c, n1 + c->k[0]);
285 n1 ^= f(c, n2 + c->k[1]);
286 n2 ^= f(c, n1 + c->k[2]);
287 n1 ^= f(c, n2 + c->k[3]);
288 n2 ^= f(c, n1 + c->k[4]);
289 n1 ^= f(c, n2 + c->k[5]);
290 n2 ^= f(c, n1 + c->k[6]);
291 n1 ^= f(c, n2 + c->k[7]);
293 n2 ^= f(c, n1 + c->k[0]);
294 n1 ^= f(c, n2 + c->k[1]);
295 n2 ^= f(c, n1 + c->k[2]);
296 n1 ^= f(c, n2 + c->k[3]);
297 n2 ^= f(c, n1 + c->k[4]);
298 n1 ^= f(c, n2 + c->k[5]);
299 n2 ^= f(c, n1 + c->k[6]);
300 n1 ^= f(c, n2 + c->k[7]);
302 n2 ^= f(c, n1 + c->k[0]);
303 n1 ^= f(c, n2 + c->k[1]);
304 n2 ^= f(c, n1 + c->k[2]);
305 n1 ^= f(c, n2 + c->k[3]);
306 n2 ^= f(c, n1 + c->k[4]);
307 n1 ^= f(c, n2 + c->k[5]);
308 n2 ^= f(c, n1 + c->k[6]);
309 n1 ^= f(c, n2 + c->k[7]);
311 n2 ^= f(c, n1 + c->k[7]);
312 n1 ^= f(c, n2 + c->k[6]);
313 n2 ^= f(c, n1 + c->k[5]);
314 n1 ^= f(c, n2 + c->k[4]);
315 n2 ^= f(c, n1 + c->k[3]);
316 n1 ^= f(c, n2 + c->k[2]);
317 n2 ^= f(c, n1 + c->k[1]);
318 n1 ^= f(c, n2 + c->k[0]);
320 out[0] = (byte) (n2 & 0xff);
321 out[1] = (byte) ((n2 >> 8) & 0xff);
322 out[2] = (byte) ((n2 >> 16) & 0xff);
323 out[3] = (byte) (n2 >> 24);
324 out[4] = (byte) (n1 & 0xff);
325 out[5] = (byte) ((n1 >> 8) & 0xff);
326 out[6] = (byte) ((n1 >> 16) & 0xff);
327 out[7] = (byte) (n1 >> 24);
330 /* Low-level decryption routine. Decrypts one 64-bit block */
331 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
333 register word32 n1, n2; /* As named in the GOST */
334 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
335 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
337 n2 ^= f(c, n1 + c->k[0]);
338 n1 ^= f(c, n2 + c->k[1]);
339 n2 ^= f(c, n1 + c->k[2]);
340 n1 ^= f(c, n2 + c->k[3]);
341 n2 ^= f(c, n1 + c->k[4]);
342 n1 ^= f(c, n2 + c->k[5]);
343 n2 ^= f(c, n1 + c->k[6]);
344 n1 ^= f(c, n2 + c->k[7]);
346 n2 ^= f(c, n1 + c->k[7]);
347 n1 ^= f(c, n2 + c->k[6]);
348 n2 ^= f(c, n1 + c->k[5]);
349 n1 ^= f(c, n2 + c->k[4]);
350 n2 ^= f(c, n1 + c->k[3]);
351 n1 ^= f(c, n2 + c->k[2]);
352 n2 ^= f(c, n1 + c->k[1]);
353 n1 ^= f(c, n2 + c->k[0]);
355 n2 ^= f(c, n1 + c->k[7]);
356 n1 ^= f(c, n2 + c->k[6]);
357 n2 ^= f(c, n1 + c->k[5]);
358 n1 ^= f(c, n2 + c->k[4]);
359 n2 ^= f(c, n1 + c->k[3]);
360 n1 ^= f(c, n2 + c->k[2]);
361 n2 ^= f(c, n1 + c->k[1]);
362 n1 ^= f(c, n2 + c->k[0]);
364 n2 ^= f(c, n1 + c->k[7]);
365 n1 ^= f(c, n2 + c->k[6]);
366 n2 ^= f(c, n1 + c->k[5]);
367 n1 ^= f(c, n2 + c->k[4]);
368 n2 ^= f(c, n1 + c->k[3]);
369 n1 ^= f(c, n2 + c->k[2]);
370 n2 ^= f(c, n1 + c->k[1]);
371 n1 ^= f(c, n2 + c->k[0]);
373 out[0] = (byte) (n2 & 0xff);
374 out[1] = (byte) ((n2 >> 8) & 0xff);
375 out[2] = (byte) ((n2 >> 16) & 0xff);
376 out[3] = (byte) (n2 >> 24);
377 out[4] = (byte) (n1 & 0xff);
378 out[5] = (byte) ((n1 >> 8) & 0xff);
379 out[6] = (byte) ((n1 >> 16) & 0xff);
380 out[7] = (byte) (n1 >> 24);
383 /* Encrypts several blocks in ECB mode */
384 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
387 for (i = 0; i < blocks; i++) {
388 gostcrypt(c, clear, cipher);
394 /* Decrypts several blocks in ECB mode */
395 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
398 for (i = 0; i < blocks; i++) {
399 gostdecrypt(c, cipher, clear);
405 /* Encrypts several full blocks in CFB mode using 8byte IV */
406 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
407 byte * cipher, int blocks)
414 memcpy(cur_iv, iv, 8);
415 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
416 gostcrypt(ctx, cur_iv, gamma);
417 for (j = 0; j < 8; j++) {
418 cur_iv[j] = out[j] = in[j] ^ gamma[j];
423 /* Decrypts several full blocks in CFB mode using 8byte IV */
424 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
425 byte * clear, int blocks)
432 memcpy(cur_iv, iv, 8);
433 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
434 gostcrypt(ctx, cur_iv, gamma);
435 for (j = 0; j < 8; j++) {
436 out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
441 /* Encrypts one block using specified key */
442 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
446 gostcrypt(c, inblock, outblock);
449 /* Set 256 bit gost89 key into context */
450 void gost_key(gost_ctx * c, const byte * k)
453 for (i = 0, j = 0; i < 8; i++, j += 4) {
455 k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
460 /* Set 256 bit Magma key into context */
461 void magma_key(gost_ctx * c, const byte * k)
464 for (i = 0, j = 0; i < 8; i++, j += 4) {
466 k[j + 3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
471 /* Retrieve 256-bit gost89 key from context */
472 void gost_get_key(gost_ctx * c, byte * k)
475 for (i = 0, j = 0; i < 8; i++, j += 4) {
476 k[j] = (byte) (c->k[i] & 0xFF);
477 k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
478 k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
479 k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
483 /* Retrieve 256-bit magma key from context */
484 void magma_get_key(gost_ctx * c, byte * k)
487 for (i = 0, j = 0; i < 8; i++, j += 4) {
488 k[j + 3] = (byte) (c->k[i] & 0xFF);
489 k[j + 2] = (byte) ((c->k[i] >> 8) & 0xFF);
490 k[j + 1] = (byte) ((c->k[i] >> 16) & 0xFF);
491 k[j + 0] = (byte) ((c->k[i] >> 24) & 0xFF);
495 /* Initalize context. Provides default value for subst_block */
496 void gost_init(gost_ctx * c, const gost_subst_block * b)
499 b = &GostR3411_94_TestParamSet;
504 /* Cleans up key from context */
505 void gost_destroy(gost_ctx * c)
507 OPENSSL_cleanse(c->k, sizeof(c->k));
511 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
512 * with substitution blocks and key buffer - 8-byte mac state buffer block
513 * 8-byte block to process.
515 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
517 register word32 n1, n2; /* As named in the GOST */
519 for (i = 0; i < 8; i++) {
520 buffer[i] ^= block[i];
522 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
524 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
526 /* Instead of swapping halves, swap names each round */
528 n2 ^= f(c, n1 + c->k[0]);
529 n1 ^= f(c, n2 + c->k[1]);
530 n2 ^= f(c, n1 + c->k[2]);
531 n1 ^= f(c, n2 + c->k[3]);
532 n2 ^= f(c, n1 + c->k[4]);
533 n1 ^= f(c, n2 + c->k[5]);
534 n2 ^= f(c, n1 + c->k[6]);
535 n1 ^= f(c, n2 + c->k[7]);
537 n2 ^= f(c, n1 + c->k[0]);
538 n1 ^= f(c, n2 + c->k[1]);
539 n2 ^= f(c, n1 + c->k[2]);
540 n1 ^= f(c, n2 + c->k[3]);
541 n2 ^= f(c, n1 + c->k[4]);
542 n1 ^= f(c, n2 + c->k[5]);
543 n2 ^= f(c, n1 + c->k[6]);
544 n1 ^= f(c, n2 + c->k[7]);
546 buffer[0] = (byte) (n1 & 0xff);
547 buffer[1] = (byte) ((n1 >> 8) & 0xff);
548 buffer[2] = (byte) ((n1 >> 16) & 0xff);
549 buffer[3] = (byte) (n1 >> 24);
550 buffer[4] = (byte) (n2 & 0xff);
551 buffer[5] = (byte) ((n2 >> 8) & 0xff);
552 buffer[6] = (byte) ((n2 >> 16) & 0xff);
553 buffer[7] = (byte) (n2 >> 24);
556 /* Get mac with specified number of bits from MAC state buffer */
557 void get_mac(byte * buffer, int nbits, byte * out)
559 int nbytes = nbits >> 3;
560 int rembits = nbits & 7;
561 int mask = rembits ? ((1 < rembits) - 1) : 0;
563 for (i = 0; i < nbytes; i++)
566 out[i] = buffer[i] & mask;
570 * Compute mac of specified length (in bits) from data. Context should be
571 * initialized with key and subst blocks
573 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
574 unsigned int data_len, unsigned char *mac)
576 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
579 for (i = 0; i + 8 <= data_len; i += 8)
580 mac_block(ctx, buffer, data + i);
583 memcpy(buf2, data + i, data_len - i);
584 mac_block(ctx, buffer, buf2);
589 mac_block(ctx, buffer, buf2);
591 get_mac(buffer, mac_len, mac);
595 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
596 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
597 const unsigned char *data, unsigned int data_len,
603 memcpy(buffer, iv, 8);
604 for (i = 0; i + 8 <= data_len; i += 8)
605 mac_block(ctx, buffer, data + i);
608 memcpy(buf2, data + i, data_len - i);
609 mac_block(ctx, buffer, buf2);
614 mac_block(ctx, buffer, buf2);
616 get_mac(buffer, mac_len, mac);
620 /* Implements key meshing algorithm by modifing ctx and IV in place */
621 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
623 unsigned char newkey[32];
624 /* Set static keymeshing key */
625 /* "Decrypt" key with keymeshing key */
626 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
628 gost_key(ctx, newkey);
629 OPENSSL_cleanse(newkey, sizeof(newkey));
630 /* Encrypt iv with new key */
632 unsigned char newiv[8];
633 gostcrypt(ctx, iv, newiv);
634 memcpy(iv, newiv, 8);
635 OPENSSL_cleanse(newiv, sizeof(newiv));
639 void acpkm_magma_key_meshing(gost_ctx * ctx)
641 unsigned char newkey[32];
644 for (i = 0; i < 4; i++) {
645 unsigned char buf[8], keybuf[8];
646 for (j = 0; j < 8; j++) {
647 buf[j] = ACPKM_D_const[8 * i + 7 - j];
649 gostcrypt(ctx, buf, keybuf);
650 memcpy(newkey + 8 * i, keybuf + 4, 4);
651 memcpy(newkey + 8 * i + 4, keybuf, 4);
652 OPENSSL_cleanse(keybuf, sizeof(keybuf));
653 OPENSSL_cleanse(buf, sizeof(buf));
656 gost_key(ctx, newkey);
657 OPENSSL_cleanse(newkey, sizeof(newkey));