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 **********************************************************************/
13 Substitution blocks from RFC 4357
15 Note: our implementation of gost 28147-89 algorithm
16 uses S-box matrix rotated 90 degrees counterclockwise, relative to
17 examples given in RFC.
22 /* Substitution blocks from test examples for GOST R 34.11-94*/
23 gost_subst_block GostR3411_94_TestParamSet = {
24 {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB,
27 {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8,
30 {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC,
33 {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3,
36 {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2,
39 {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0,
42 {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7,
45 {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF,
49 /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
50 gost_subst_block GostR3411_94_CryptoProParamSet = {
51 {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0,
54 {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2,
57 {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE,
60 {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD,
63 {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB,
66 {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA,
69 {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE,
72 {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2,
76 /* Test paramset from GOST 28147 */
77 gost_subst_block Gost28147_TestParamSet = {
78 {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4,
81 {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA,
84 {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE,
87 {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1,
90 {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4,
93 {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF,
96 {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0,
99 {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7,
103 /* 1.2.643.2.2.31.1 */
104 gost_subst_block Gost28147_CryptoProParamSetA = {
105 {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7,
108 {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3,
111 {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF,
114 {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7,
117 {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8,
120 {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7,
123 {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4,
126 {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0,
130 /* 1.2.643.2.2.31.2 */
131 gost_subst_block Gost28147_CryptoProParamSetB = {
132 {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD,
135 {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF,
138 {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0,
141 {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8,
144 {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE,
147 {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6,
150 {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8,
153 {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6,
157 /* 1.2.643.2.2.31.3 */
158 gost_subst_block Gost28147_CryptoProParamSetC = {
159 {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9,
162 {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1,
165 {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0,
168 {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF,
171 {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF,
174 {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE,
177 {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA,
180 {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7,
184 /* 1.2.643.2.2.31.4 */
185 gost_subst_block Gost28147_CryptoProParamSetD = {
186 {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD,
189 {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA,
192 {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9,
195 {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE,
198 {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3,
201 {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3,
204 {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA,
207 {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB,
211 /* 1.2.643.7.1.2.5.1.1 */
212 gost_subst_block Gost28147_TC26ParamSetZ = {
213 {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc,
216 {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa,
219 {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3,
222 {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4,
225 {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe,
228 {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9,
231 {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd,
234 {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3,
238 const byte CryptoProKeyMeshingKey[] = {
239 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
240 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
241 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
242 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
245 /* Initialization of gost_ctx subst blocks*/
246 static void kboxinit(gost_ctx * c, const gost_subst_block * b)
250 for (i = 0; i < 256; i++) {
251 c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
252 c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
253 c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
254 c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
259 /* Part of GOST 28147 algorithm moved into separate function */
260 static word32 f(gost_ctx * c, word32 x)
262 x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
263 c->k43[x >> 8 & 255] | c->k21[x & 255];
264 /* Rotate left 11 bits */
265 return x << 11 | x >> (32 - 11);
268 /* Low-level encryption routine - encrypts one 64 bit block*/
269 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
271 register word32 n1, n2; /* As named in the GOST */
272 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
273 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
274 /* Instead of swapping halves, swap names each round */
276 n2 ^= f(c, n1 + c->k[0]);
277 n1 ^= f(c, n2 + c->k[1]);
278 n2 ^= f(c, n1 + c->k[2]);
279 n1 ^= f(c, n2 + c->k[3]);
280 n2 ^= f(c, n1 + c->k[4]);
281 n1 ^= f(c, n2 + c->k[5]);
282 n2 ^= f(c, n1 + c->k[6]);
283 n1 ^= f(c, n2 + c->k[7]);
285 n2 ^= f(c, n1 + c->k[0]);
286 n1 ^= f(c, n2 + c->k[1]);
287 n2 ^= f(c, n1 + c->k[2]);
288 n1 ^= f(c, n2 + c->k[3]);
289 n2 ^= f(c, n1 + c->k[4]);
290 n1 ^= f(c, n2 + c->k[5]);
291 n2 ^= f(c, n1 + c->k[6]);
292 n1 ^= f(c, n2 + c->k[7]);
294 n2 ^= f(c, n1 + c->k[0]);
295 n1 ^= f(c, n2 + c->k[1]);
296 n2 ^= f(c, n1 + c->k[2]);
297 n1 ^= f(c, n2 + c->k[3]);
298 n2 ^= f(c, n1 + c->k[4]);
299 n1 ^= f(c, n2 + c->k[5]);
300 n2 ^= f(c, n1 + c->k[6]);
301 n1 ^= f(c, n2 + c->k[7]);
303 n2 ^= f(c, n1 + c->k[7]);
304 n1 ^= f(c, n2 + c->k[6]);
305 n2 ^= f(c, n1 + c->k[5]);
306 n1 ^= f(c, n2 + c->k[4]);
307 n2 ^= f(c, n1 + c->k[3]);
308 n1 ^= f(c, n2 + c->k[2]);
309 n2 ^= f(c, n1 + c->k[1]);
310 n1 ^= f(c, n2 + c->k[0]);
312 out[0] = (byte) (n2 & 0xff);
313 out[1] = (byte) ((n2 >> 8) & 0xff);
314 out[2] = (byte) ((n2 >> 16) & 0xff);
315 out[3] = (byte) (n2 >> 24);
316 out[4] = (byte) (n1 & 0xff);
317 out[5] = (byte) ((n1 >> 8) & 0xff);
318 out[6] = (byte) ((n1 >> 16) & 0xff);
319 out[7] = (byte) (n1 >> 24);
322 /* Low-level decryption routine. Decrypts one 64-bit block */
323 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
325 register word32 n1, n2; /* As named in the GOST */
326 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
327 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
329 n2 ^= f(c, n1 + c->k[0]);
330 n1 ^= f(c, n2 + c->k[1]);
331 n2 ^= f(c, n1 + c->k[2]);
332 n1 ^= f(c, n2 + c->k[3]);
333 n2 ^= f(c, n1 + c->k[4]);
334 n1 ^= f(c, n2 + c->k[5]);
335 n2 ^= f(c, n1 + c->k[6]);
336 n1 ^= f(c, n2 + c->k[7]);
338 n2 ^= f(c, n1 + c->k[7]);
339 n1 ^= f(c, n2 + c->k[6]);
340 n2 ^= f(c, n1 + c->k[5]);
341 n1 ^= f(c, n2 + c->k[4]);
342 n2 ^= f(c, n1 + c->k[3]);
343 n1 ^= f(c, n2 + c->k[2]);
344 n2 ^= f(c, n1 + c->k[1]);
345 n1 ^= f(c, n2 + c->k[0]);
347 n2 ^= f(c, n1 + c->k[7]);
348 n1 ^= f(c, n2 + c->k[6]);
349 n2 ^= f(c, n1 + c->k[5]);
350 n1 ^= f(c, n2 + c->k[4]);
351 n2 ^= f(c, n1 + c->k[3]);
352 n1 ^= f(c, n2 + c->k[2]);
353 n2 ^= f(c, n1 + c->k[1]);
354 n1 ^= f(c, n2 + c->k[0]);
356 n2 ^= f(c, n1 + c->k[7]);
357 n1 ^= f(c, n2 + c->k[6]);
358 n2 ^= f(c, n1 + c->k[5]);
359 n1 ^= f(c, n2 + c->k[4]);
360 n2 ^= f(c, n1 + c->k[3]);
361 n1 ^= f(c, n2 + c->k[2]);
362 n2 ^= f(c, n1 + c->k[1]);
363 n1 ^= f(c, n2 + c->k[0]);
365 out[0] = (byte) (n2 & 0xff);
366 out[1] = (byte) ((n2 >> 8) & 0xff);
367 out[2] = (byte) ((n2 >> 16) & 0xff);
368 out[3] = (byte) (n2 >> 24);
369 out[4] = (byte) (n1 & 0xff);
370 out[5] = (byte) ((n1 >> 8) & 0xff);
371 out[6] = (byte) ((n1 >> 16) & 0xff);
372 out[7] = (byte) (n1 >> 24);
375 /* Encrypts several blocks in ECB mode */
376 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
379 for (i = 0; i < blocks; i++) {
380 gostcrypt(c, clear, cipher);
386 /* Decrypts several blocks in ECB mode */
387 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
390 for (i = 0; i < blocks; i++) {
391 gostdecrypt(c, cipher, clear);
397 /* Encrypts several full blocks in CFB mode using 8byte IV */
398 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
399 byte * cipher, int blocks)
406 memcpy(cur_iv, iv, 8);
407 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
408 gostcrypt(ctx, cur_iv, gamma);
409 for (j = 0; j < 8; j++) {
410 cur_iv[j] = out[j] = in[j] ^ gamma[j];
415 /* Decrypts several full blocks in CFB mode using 8byte IV */
416 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
417 byte * clear, int blocks)
424 memcpy(cur_iv, iv, 8);
425 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
426 gostcrypt(ctx, cur_iv, gamma);
427 for (j = 0; j < 8; j++) {
428 out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
433 /* Encrypts one block using specified key */
434 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
438 gostcrypt(c, inblock, outblock);
441 /* Set 256 bit key into context */
442 void gost_key(gost_ctx * c, const byte * k)
445 for (i = 0, j = 0; i < 8; i++, j += 4) {
447 k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
452 /* Retrieve 256-bit key from context */
453 void gost_get_key(gost_ctx * c, byte * k)
456 for (i = 0, j = 0; i < 8; i++, j += 4) {
457 k[j] = (byte) (c->k[i] & 0xFF);
458 k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
459 k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
460 k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
464 /* Initalize context. Provides default value for subst_block */
465 void gost_init(gost_ctx * c, const gost_subst_block * b)
468 b = &GostR3411_94_TestParamSet;
473 /* Cleans up key from context */
474 void gost_destroy(gost_ctx * c)
477 for (i = 0; i < 8; i++)
482 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
483 * with substitution blocks and key buffer - 8-byte mac state buffer block
484 * 8-byte block to process.
486 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
488 register word32 n1, n2; /* As named in the GOST */
490 for (i = 0; i < 8; i++) {
491 buffer[i] ^= block[i];
493 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
495 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
497 /* Instead of swapping halves, swap names each round */
499 n2 ^= f(c, n1 + c->k[0]);
500 n1 ^= f(c, n2 + c->k[1]);
501 n2 ^= f(c, n1 + c->k[2]);
502 n1 ^= f(c, n2 + c->k[3]);
503 n2 ^= f(c, n1 + c->k[4]);
504 n1 ^= f(c, n2 + c->k[5]);
505 n2 ^= f(c, n1 + c->k[6]);
506 n1 ^= f(c, n2 + c->k[7]);
508 n2 ^= f(c, n1 + c->k[0]);
509 n1 ^= f(c, n2 + c->k[1]);
510 n2 ^= f(c, n1 + c->k[2]);
511 n1 ^= f(c, n2 + c->k[3]);
512 n2 ^= f(c, n1 + c->k[4]);
513 n1 ^= f(c, n2 + c->k[5]);
514 n2 ^= f(c, n1 + c->k[6]);
515 n1 ^= f(c, n2 + c->k[7]);
517 buffer[0] = (byte) (n1 & 0xff);
518 buffer[1] = (byte) ((n1 >> 8) & 0xff);
519 buffer[2] = (byte) ((n1 >> 16) & 0xff);
520 buffer[3] = (byte) (n1 >> 24);
521 buffer[4] = (byte) (n2 & 0xff);
522 buffer[5] = (byte) ((n2 >> 8) & 0xff);
523 buffer[6] = (byte) ((n2 >> 16) & 0xff);
524 buffer[7] = (byte) (n2 >> 24);
527 /* Get mac with specified number of bits from MAC state buffer */
528 void get_mac(byte * buffer, int nbits, byte * out)
530 int nbytes = nbits >> 3;
531 int rembits = nbits & 7;
532 int mask = rembits ? ((1 < rembits) - 1) : 0;
534 for (i = 0; i < nbytes; i++)
537 out[i] = buffer[i] & mask;
541 * Compute mac of specified length (in bits) from data. Context should be
542 * initialized with key and subst blocks
544 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
545 unsigned int data_len, unsigned char *mac)
547 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
550 for (i = 0; i + 8 <= data_len; i += 8)
551 mac_block(ctx, buffer, data + i);
554 memcpy(buf2, data + i, data_len - i);
555 mac_block(ctx, buffer, buf2);
560 mac_block(ctx, buffer, buf2);
562 get_mac(buffer, mac_len, mac);
566 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
567 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
568 const unsigned char *data, unsigned int data_len,
574 memcpy(buffer, iv, 8);
575 for (i = 0; i + 8 <= data_len; i += 8)
576 mac_block(ctx, buffer, data + i);
579 memcpy(buf2, data + i, data_len - i);
580 mac_block(ctx, buffer, buf2);
585 mac_block(ctx, buffer, buf2);
587 get_mac(buffer, mac_len, mac);
591 /* Implements key meshing algorithm by modifing ctx and IV in place */
592 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
594 unsigned char newkey[32], newiv[8];
595 /* Set static keymeshing key */
596 /* "Decrypt" key with keymeshing key */
597 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
599 gost_key(ctx, newkey);
600 /* Encrypt iv with new key */
601 gostcrypt(ctx, iv, newiv);
602 memcpy(iv, newiv, 8);