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 encryption routine - encrypts one 64 bit block*/
332 void magmacrypt(gost_ctx * c, const byte * in, byte * out)
334 register word32 n1, n2; /* As named in the GOST */
335 n1 = in[7-0] | (in[7-1] << 8) | (in[7-2] << 16) | ((word32) in[7-3] << 24);
336 n2 = in[7-4] | (in[7-5] << 8) | (in[7-6] << 16) | ((word32) in[7-7] << 24);
337 /* Instead of swapping halves, swap names each round */
339 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
340 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
341 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
342 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
343 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
344 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
345 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
346 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
348 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
349 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
350 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
351 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
352 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
353 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
354 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
355 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
357 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
358 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
359 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
360 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
361 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
362 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
363 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
364 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
366 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
367 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
368 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
369 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
370 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
371 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
372 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
373 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
375 out[7-0] = (byte) (n2 & 0xff);
376 out[7-1] = (byte) ((n2 >> 8) & 0xff);
377 out[7-2] = (byte) ((n2 >> 16) & 0xff);
378 out[7-3] = (byte) (n2 >> 24);
379 out[7-4] = (byte) (n1 & 0xff);
380 out[7-5] = (byte) ((n1 >> 8) & 0xff);
381 out[7-6] = (byte) ((n1 >> 16) & 0xff);
382 out[7-7] = (byte) (n1 >> 24);
385 /* Low-level decryption routine. Decrypts one 64-bit block */
386 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
388 register word32 n1, n2; /* As named in the GOST */
389 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
390 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
392 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
393 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
394 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
395 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
396 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
397 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
398 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
399 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
401 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
402 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
403 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
404 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
405 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
406 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
407 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
408 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
410 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
411 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
412 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
413 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
414 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
415 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
416 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
417 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
419 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
420 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
421 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
422 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
423 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
424 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
425 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
426 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
428 out[0] = (byte) (n2 & 0xff);
429 out[1] = (byte) ((n2 >> 8) & 0xff);
430 out[2] = (byte) ((n2 >> 16) & 0xff);
431 out[3] = (byte) (n2 >> 24);
432 out[4] = (byte) (n1 & 0xff);
433 out[5] = (byte) ((n1 >> 8) & 0xff);
434 out[6] = (byte) ((n1 >> 16) & 0xff);
435 out[7] = (byte) (n1 >> 24);
438 /* Low-level decryption routine. Decrypts one 64-bit block */
439 void magmadecrypt(gost_ctx * c, const byte * in, byte * out)
441 register word32 n1, n2; /* As named in the GOST */
442 n1 = in[7-0] | (in[7-1] << 8) | (in[7-2] << 16) | ((word32) in[7-3] << 24);
443 n2 = in[7-4] | (in[7-5] << 8) | (in[7-6] << 16) | ((word32) in[7-7] << 24);
445 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
446 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
447 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
448 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
449 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
450 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
451 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
452 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
454 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
455 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
456 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
457 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
458 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
459 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
460 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
461 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
463 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
464 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
465 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
466 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
467 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
468 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
469 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
470 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
472 n2 ^= f(c, n1 + c->key[7] + c->mask[7]);
473 n1 ^= f(c, n2 + c->key[6] + c->mask[6]);
474 n2 ^= f(c, n1 + c->key[5] + c->mask[5]);
475 n1 ^= f(c, n2 + c->key[4] + c->mask[4]);
476 n2 ^= f(c, n1 + c->key[3] + c->mask[3]);
477 n1 ^= f(c, n2 + c->key[2] + c->mask[2]);
478 n2 ^= f(c, n1 + c->key[1] + c->mask[1]);
479 n1 ^= f(c, n2 + c->key[0] + c->mask[0]);
481 out[7-0] = (byte) (n2 & 0xff);
482 out[7-1] = (byte) ((n2 >> 8) & 0xff);
483 out[7-2] = (byte) ((n2 >> 16) & 0xff);
484 out[7-3] = (byte) (n2 >> 24);
485 out[7-4] = (byte) (n1 & 0xff);
486 out[7-5] = (byte) ((n1 >> 8) & 0xff);
487 out[7-6] = (byte) ((n1 >> 16) & 0xff);
488 out[7-7] = (byte) (n1 >> 24);
492 /* Encrypts several blocks in ECB mode */
493 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
496 for (i = 0; i < blocks; i++) {
497 gostcrypt(c, clear, cipher);
503 /* Decrypts several blocks in ECB mode */
504 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
507 for (i = 0; i < blocks; i++) {
508 gostdecrypt(c, cipher, clear);
514 /* Encrypts several full blocks in CFB mode using 8byte IV */
515 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
516 byte * cipher, int blocks)
523 memcpy(cur_iv, iv, 8);
524 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
525 gostcrypt(ctx, cur_iv, gamma);
526 for (j = 0; j < 8; j++) {
527 cur_iv[j] = out[j] = in[j] ^ gamma[j];
532 /* Decrypts several full blocks in CFB mode using 8byte IV */
533 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
534 byte * clear, int blocks)
541 memcpy(cur_iv, iv, 8);
542 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
543 gostcrypt(ctx, cur_iv, gamma);
544 for (j = 0; j < 8; j++) {
545 out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
550 /* Encrypts one block using specified key */
551 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
554 gost_key_nomask(c, key);
555 gostcrypt(c, inblock, outblock);
558 static void gost_key_impl(gost_ctx * c, const byte * k)
561 for (i = 0, j = 0; i < 8; ++i, j += 4) {
563 (k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
568 /* Set 256 bit gost89 key into context */
569 void gost_key(gost_ctx * c, const byte * k)
571 RAND_priv_bytes((unsigned char *)c->mask, sizeof(c->mask));
575 /* Set 256 bit gost89 key into context without key mask */
576 void gost_key_nomask(gost_ctx * c, const byte * k)
578 memset(c->mask, 0, sizeof(c->mask));
582 /* Set 256 bit Magma key into context */
583 void magma_key(gost_ctx * c, const byte * k)
586 RAND_priv_bytes((unsigned char *)c->mask, sizeof(c->mask));
587 for (i = 0, j = 0; i < 8; ++i, j += 4) {
589 (k[j + 3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
594 void magma_master_key(gost_ctx *c, const byte *k) {
595 memcpy(c->master_key, k, sizeof(c->master_key));
598 /* Retrieve 256-bit gost89 key from context */
599 void gost_get_key(gost_ctx * c, byte * k)
602 for (i = 0, j = 0; i < 8; i++, j += 4) {
603 k[j] = (byte)((c->key[i] + c->mask[i]) & 0xFF);
604 k[j+1] = (byte)(((c->key[i] + c->mask[i]) >> 8 )& 0xFF);
605 k[j+2] = (byte)(((c->key[i] + c->mask[i]) >> 16) & 0xFF);
606 k[j+3] = (byte)(((c->key[i] + c->mask[i]) >> 24) & 0xFF);
610 /* Retrieve 256-bit magma key from context */
611 void magma_get_key(gost_ctx * c, byte * k)
614 for (i = 0, j = 0; i < 8; i++, j += 4) {
615 k[j + 3] = (byte) ((c->key[i] + c->mask[i]) & 0xFF);
616 k[j + 2] = (byte) (((c->key[i] + c->mask[i]) >> 8) & 0xFF);
617 k[j + 1] = (byte) (((c->key[i] + c->mask[i]) >> 16) & 0xFF);
618 k[j + 0] = (byte) (((c->key[i] + c->mask[i]) >> 24) & 0xFF);
622 /* Initalize context. Provides default value for subst_block */
623 void gost_init(gost_ctx * c, const gost_subst_block * b)
626 b = &GostR3411_94_TestParamSet;
631 /* Cleans up key from context */
632 void gost_destroy(gost_ctx * c)
634 OPENSSL_cleanse(c->master_key, sizeof(c->master_key));
635 OPENSSL_cleanse(c->key, sizeof(c->key));
636 OPENSSL_cleanse(c->mask, sizeof(c->mask));
640 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
641 * with substitution blocks and key buffer - 8-byte mac state buffer block
642 * 8-byte block to process.
644 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
646 register word32 n1, n2; /* As named in the GOST */
648 for (i = 0; i < 8; i++) {
649 buffer[i] ^= block[i];
651 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
653 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
655 /* Instead of swapping halves, swap names each round */
657 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
658 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
659 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
660 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
661 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
662 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
663 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
664 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
666 n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
667 n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
668 n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
669 n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
670 n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
671 n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
672 n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
673 n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
675 buffer[0] = (byte) (n1 & 0xff);
676 buffer[1] = (byte) ((n1 >> 8) & 0xff);
677 buffer[2] = (byte) ((n1 >> 16) & 0xff);
678 buffer[3] = (byte) (n1 >> 24);
679 buffer[4] = (byte) (n2 & 0xff);
680 buffer[5] = (byte) ((n2 >> 8) & 0xff);
681 buffer[6] = (byte) ((n2 >> 16) & 0xff);
682 buffer[7] = (byte) (n2 >> 24);
685 /* Get mac with specified number of bits from MAC state buffer */
686 void get_mac(byte * buffer, int nbits, byte * out)
688 int nbytes = nbits >> 3;
689 int rembits = nbits & 7;
690 int mask = rembits ? ((1 < rembits) - 1) : 0;
692 for (i = 0; i < nbytes; i++)
695 out[i] = buffer[i] & mask;
699 * Compute mac of specified length (in bits) from data. Context should be
700 * initialized with key and subst blocks
702 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
703 unsigned int data_len, unsigned char *mac)
705 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
708 for (i = 0; i + 8 <= data_len; i += 8)
709 mac_block(ctx, buffer, data + i);
712 memcpy(buf2, data + i, data_len - i);
713 mac_block(ctx, buffer, buf2);
718 mac_block(ctx, buffer, buf2);
720 get_mac(buffer, mac_len, mac);
724 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
725 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
726 const unsigned char *data, unsigned int data_len,
732 memcpy(buffer, iv, 8);
733 for (i = 0; i + 8 <= data_len; i += 8)
734 mac_block(ctx, buffer, data + i);
737 memcpy(buf2, data + i, data_len - i);
738 mac_block(ctx, buffer, buf2);
743 mac_block(ctx, buffer, buf2);
745 get_mac(buffer, mac_len, mac);
749 /* Implements key meshing algorithm by modifing ctx and IV in place */
750 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
752 unsigned char newkey[32];
753 /* Set static keymeshing key */
754 /* "Decrypt" key with keymeshing key */
755 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
757 gost_key(ctx, newkey);
758 OPENSSL_cleanse(newkey, sizeof(newkey));
759 /* Encrypt iv with new key */
761 unsigned char newiv[8];
762 gostcrypt(ctx, iv, newiv);
763 memcpy(iv, newiv, 8);
764 OPENSSL_cleanse(newiv, sizeof(newiv));
768 void acpkm_magma_key_meshing(gost_ctx * ctx)
770 unsigned char newkey[32];
772 for (i = 0; i < 4; i++) {
773 magmacrypt(ctx, ACPKM_D_const + 8 * i, newkey + 8 * i);
776 magma_key(ctx, newkey);
777 OPENSSL_cleanse(newkey, sizeof(newkey));