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>
12 #include <openssl/rand.h>
15 Substitution blocks from RFC 4357
17 Note: our implementation of gost 28147-89 algorithm
18 uses S-box matrix rotated 90 degrees counterclockwise, relative to
19 examples given in RFC.
24 /* Substitution blocks from test examples for GOST R 34.11-94*/
25 gost_subst_block GostR3411_94_TestParamSet = {
26 {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB,
29 {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8,
32 {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC,
35 {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3,
38 {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2,
41 {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0,
44 {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7,
47 {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF,
51 /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
52 gost_subst_block GostR3411_94_CryptoProParamSet = {
53 {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0,
56 {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2,
59 {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE,
62 {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD,
65 {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB,
68 {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA,
71 {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE,
74 {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2,
78 /* Test paramset from GOST 28147 */
79 gost_subst_block Gost28147_TestParamSet = {
80 {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4,
83 {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA,
86 {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE,
89 {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1,
92 {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4,
95 {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF,
98 {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0,
101 {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7,
105 /* 1.2.643.2.2.31.1 */
106 gost_subst_block Gost28147_CryptoProParamSetA = {
107 {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7,
110 {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3,
113 {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF,
116 {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7,
119 {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8,
122 {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7,
125 {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4,
128 {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0,
132 /* 1.2.643.2.2.31.2 */
133 gost_subst_block Gost28147_CryptoProParamSetB = {
134 {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD,
137 {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF,
140 {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0,
143 {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8,
146 {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE,
149 {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6,
152 {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8,
155 {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6,
159 /* 1.2.643.2.2.31.3 */
160 gost_subst_block Gost28147_CryptoProParamSetC = {
161 {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9,
164 {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1,
167 {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0,
170 {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF,
173 {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF,
176 {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE,
179 {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA,
182 {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7,
186 /* 1.2.643.2.2.31.4 */
187 gost_subst_block Gost28147_CryptoProParamSetD = {
188 {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD,
191 {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA,
194 {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9,
197 {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE,
200 {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3,
203 {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3,
206 {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA,
209 {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB,
213 /* 1.2.643.7.1.2.5.1.1 */
214 gost_subst_block Gost28147_TC26ParamSetZ = {
215 {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc,
218 {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa,
221 {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3,
224 {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4,
227 {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe,
230 {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9,
233 {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd,
236 {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3,
240 const byte CryptoProKeyMeshingKey[] = {
241 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
242 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
243 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
244 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
247 const byte ACPKM_D_const[] = {
248 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
249 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
250 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
251 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
254 /* Initialization of gost_ctx subst blocks*/
255 void kboxinit(gost_ctx * c, const gost_subst_block * b)
259 for (i = 0; i < 256; i++) {
260 c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
261 c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
262 c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
263 c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
268 /* Part of GOST 28147 algorithm moved into separate function */
269 static word32 f(gost_ctx * c, word32 x)
271 x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
272 c->k43[x >> 8 & 255] | c->k21[x & 255];
273 /* Rotate left 11 bits */
274 return x << 11 | x >> (32 - 11);
277 /* Low-level encryption routine - encrypts one 64 bit block*/
278 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
280 register word32 n1, n2; /* As named in the GOST */
281 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
282 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
283 /* Instead of swapping halves, swap names each round */
285 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
286 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
287 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
288 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
289 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
290 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
291 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
292 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
294 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
295 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
296 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
297 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
298 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
299 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
300 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
301 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
303 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
304 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
305 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
306 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
307 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
308 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
309 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
310 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
312 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
313 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
314 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
315 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
316 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
317 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
318 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
319 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
321 out[0] = (byte) (n2 & 0xff);
322 out[1] = (byte) ((n2 >> 8) & 0xff);
323 out[2] = (byte) ((n2 >> 16) & 0xff);
324 out[3] = (byte) (n2 >> 24);
325 out[4] = (byte) (n1 & 0xff);
326 out[5] = (byte) ((n1 >> 8) & 0xff);
327 out[6] = (byte) ((n1 >> 16) & 0xff);
328 out[7] = (byte) (n1 >> 24);
331 /* Low-level decryption routine. Decrypts one 64-bit block */
332 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
334 register word32 n1, n2; /* As named in the GOST */
335 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
336 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
338 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
339 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
340 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
341 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
342 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
343 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
344 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
345 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
347 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
348 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
349 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
350 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
351 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
352 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
353 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
354 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
356 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
357 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
358 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
359 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
360 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
361 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
362 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
363 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
365 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
366 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
367 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
368 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
369 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
370 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
371 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
372 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
374 out[0] = (byte) (n2 & 0xff);
375 out[1] = (byte) ((n2 >> 8) & 0xff);
376 out[2] = (byte) ((n2 >> 16) & 0xff);
377 out[3] = (byte) (n2 >> 24);
378 out[4] = (byte) (n1 & 0xff);
379 out[5] = (byte) ((n1 >> 8) & 0xff);
380 out[6] = (byte) ((n1 >> 16) & 0xff);
381 out[7] = (byte) (n1 >> 24);
385 /* Encrypts several blocks in ECB mode */
386 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
389 for (i = 0; i < blocks; i++) {
390 gostcrypt(c, clear, cipher);
396 /* Decrypts several blocks in ECB mode */
397 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
400 for (i = 0; i < blocks; i++) {
401 gostdecrypt(c, cipher, clear);
407 /* Encrypts several full blocks in CFB mode using 8byte IV */
408 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
409 byte * cipher, int blocks)
416 memcpy(cur_iv, iv, 8);
417 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
418 gostcrypt(ctx, cur_iv, gamma);
419 for (j = 0; j < 8; j++) {
420 cur_iv[j] = out[j] = in[j] ^ gamma[j];
425 /* Decrypts several full blocks in CFB mode using 8byte IV */
426 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
427 byte * clear, int blocks)
434 memcpy(cur_iv, iv, 8);
435 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
436 gostcrypt(ctx, cur_iv, gamma);
437 for (j = 0; j < 8; j++) {
438 out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
443 /* Encrypts one block using specified key */
444 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
447 gost_key_nomask(c, key);
448 gostcrypt(c, inblock, outblock);
451 static void gost_key_impl(gost_ctx * c, const byte * k)
454 for (i = 0, j = 0; i < 8; ++i, j += 4) {
456 (k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
461 /* Set 256 bit gost89 key into context */
462 void gost_key(gost_ctx * c, const byte * k)
464 RAND_priv_bytes((unsigned char *)c->mask, sizeof(c->mask));
468 /* Set 256 bit gost89 key into context without key mask */
469 void gost_key_nomask(gost_ctx * c, const byte * k)
471 memset(c->mask, 0, sizeof(c->mask));
475 /* Set 256 bit Magma key into context */
476 void magma_key(gost_ctx * c, const byte * k)
479 RAND_priv_bytes((unsigned char *)c->mask, sizeof(c->mask));
480 for (i = 0, j = 0; i < 8; ++i, j += 4) {
482 (k[j + 3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
487 void magma_master_key(gost_ctx *c, const byte *k) {
488 memcpy(c->master_key, k, sizeof(c->master_key));
491 /* Retrieve 256-bit gost89 key from context */
492 void gost_get_key(gost_ctx * c, byte * k)
495 for (i = 0, j = 0; i < 8; i++, j += 4) {
496 k[j] = (byte)((c->key[i] + c->mask[i]) & 0xFF);
497 k[j+1] = (byte)(((c->key[i] + c->mask[i]) >> 8 )& 0xFF);
498 k[j+2] = (byte)(((c->key[i] + c->mask[i]) >> 16) & 0xFF);
499 k[j+3] = (byte)(((c->key[i] + c->mask[i]) >> 24) & 0xFF);
503 /* Retrieve 256-bit magma key from context */
504 void magma_get_key(gost_ctx * c, byte * k)
507 for (i = 0, j = 0; i < 8; i++, j += 4) {
508 k[j + 3] = (byte) ((c->key[i] + c->mask[i]) & 0xFF);
509 k[j + 2] = (byte) (((c->key[i] + c->mask[i]) >> 8) & 0xFF);
510 k[j + 1] = (byte) (((c->key[i] + c->mask[i]) >> 16) & 0xFF);
511 k[j + 0] = (byte) (((c->key[i] + c->mask[i]) >> 24) & 0xFF);
515 /* Initalize context. Provides default value for subst_block */
516 void gost_init(gost_ctx * c, const gost_subst_block * b)
519 b = &GostR3411_94_TestParamSet;
524 /* Cleans up key from context */
525 void gost_destroy(gost_ctx * c)
527 OPENSSL_cleanse(c->master_key, sizeof(c->master_key));
528 OPENSSL_cleanse(c->key, sizeof(c->key));
529 OPENSSL_cleanse(c->mask, sizeof(c->mask));
533 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
534 * with substitution blocks and key buffer - 8-byte mac state buffer block
535 * 8-byte block to process.
537 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
539 register word32 n1, n2; /* As named in the GOST */
541 for (i = 0; i < 8; i++) {
542 buffer[i] ^= block[i];
544 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
546 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
548 /* Instead of swapping halves, swap names each round */
550 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
551 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
552 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
553 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
554 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
555 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
556 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
557 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
559 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
560 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
561 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
562 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
563 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
564 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
565 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
566 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
568 buffer[0] = (byte) (n1 & 0xff);
569 buffer[1] = (byte) ((n1 >> 8) & 0xff);
570 buffer[2] = (byte) ((n1 >> 16) & 0xff);
571 buffer[3] = (byte) (n1 >> 24);
572 buffer[4] = (byte) (n2 & 0xff);
573 buffer[5] = (byte) ((n2 >> 8) & 0xff);
574 buffer[6] = (byte) ((n2 >> 16) & 0xff);
575 buffer[7] = (byte) (n2 >> 24);
578 /* Get mac with specified number of bits from MAC state buffer */
579 void get_mac(byte * buffer, int nbits, byte * out)
581 int nbytes = nbits >> 3;
582 int rembits = nbits & 7;
583 int mask = rembits ? ((1 < rembits) - 1) : 0;
585 for (i = 0; i < nbytes; i++)
588 out[i] = buffer[i] & mask;
592 * Compute mac of specified length (in bits) from data. Context should be
593 * initialized with key and subst blocks
595 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
596 unsigned int data_len, unsigned char *mac)
598 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
601 for (i = 0; i + 8 <= data_len; i += 8)
602 mac_block(ctx, buffer, data + i);
605 memcpy(buf2, data + i, data_len - i);
606 mac_block(ctx, buffer, buf2);
611 mac_block(ctx, buffer, buf2);
613 get_mac(buffer, mac_len, mac);
617 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
618 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
619 const unsigned char *data, unsigned int data_len,
625 memcpy(buffer, iv, 8);
626 for (i = 0; i + 8 <= data_len; i += 8)
627 mac_block(ctx, buffer, data + i);
630 memcpy(buf2, data + i, data_len - i);
631 mac_block(ctx, buffer, buf2);
636 mac_block(ctx, buffer, buf2);
638 get_mac(buffer, mac_len, mac);
642 /* Implements key meshing algorithm by modifing ctx and IV in place */
643 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
645 unsigned char newkey[32];
646 /* Set static keymeshing key */
647 /* "Decrypt" key with keymeshing key */
648 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
650 gost_key(ctx, newkey);
651 OPENSSL_cleanse(newkey, sizeof(newkey));
652 /* Encrypt iv with new key */
654 unsigned char newiv[8];
655 gostcrypt(ctx, iv, newiv);
656 memcpy(iv, newiv, 8);
657 OPENSSL_cleanse(newiv, sizeof(newiv));
661 void acpkm_magma_key_meshing(gost_ctx * ctx)
663 unsigned char newkey[32];
666 for (i = 0; i < 4; i++) {
667 unsigned char buf[8], keybuf[8];
668 for (j = 0; j < 8; j++) {
669 buf[j] = ACPKM_D_const[8 * i + 7 - j];
671 gostcrypt(ctx, buf, keybuf);
672 memcpy(newkey + 8 * i, keybuf + 4, 4);
673 memcpy(newkey + 8 * i + 4, keybuf, 4);
674 OPENSSL_cleanse(keybuf, sizeof(keybuf));
675 OPENSSL_cleanse(buf, sizeof(buf));
678 gost_key(ctx, newkey);
679 OPENSSL_cleanse(newkey, sizeof(newkey));