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 const byte CryptoProKeyMeshingKey[] = {
212 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
213 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
214 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
215 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
218 /* Initialization of gost_ctx subst blocks*/
219 static void kboxinit(gost_ctx * c, const gost_subst_block * b)
223 for (i = 0; i < 256; i++) {
224 c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
225 c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
226 c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
227 c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
232 /* Part of GOST 28147 algorithm moved into separate function */
233 static word32 f(gost_ctx * c, word32 x)
235 x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
236 c->k43[x >> 8 & 255] | c->k21[x & 255];
237 /* Rotate left 11 bits */
238 return x << 11 | x >> (32 - 11);
241 /* Low-level encryption routine - encrypts one 64 bit block*/
242 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
244 register word32 n1, n2; /* As named in the GOST */
245 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
246 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
247 /* Instead of swapping halves, swap names each round */
249 n2 ^= f(c, n1 + c->k[0]);
250 n1 ^= f(c, n2 + c->k[1]);
251 n2 ^= f(c, n1 + c->k[2]);
252 n1 ^= f(c, n2 + c->k[3]);
253 n2 ^= f(c, n1 + c->k[4]);
254 n1 ^= f(c, n2 + c->k[5]);
255 n2 ^= f(c, n1 + c->k[6]);
256 n1 ^= f(c, n2 + c->k[7]);
258 n2 ^= f(c, n1 + c->k[0]);
259 n1 ^= f(c, n2 + c->k[1]);
260 n2 ^= f(c, n1 + c->k[2]);
261 n1 ^= f(c, n2 + c->k[3]);
262 n2 ^= f(c, n1 + c->k[4]);
263 n1 ^= f(c, n2 + c->k[5]);
264 n2 ^= f(c, n1 + c->k[6]);
265 n1 ^= f(c, n2 + c->k[7]);
267 n2 ^= f(c, n1 + c->k[0]);
268 n1 ^= f(c, n2 + c->k[1]);
269 n2 ^= f(c, n1 + c->k[2]);
270 n1 ^= f(c, n2 + c->k[3]);
271 n2 ^= f(c, n1 + c->k[4]);
272 n1 ^= f(c, n2 + c->k[5]);
273 n2 ^= f(c, n1 + c->k[6]);
274 n1 ^= f(c, n2 + c->k[7]);
276 n2 ^= f(c, n1 + c->k[7]);
277 n1 ^= f(c, n2 + c->k[6]);
278 n2 ^= f(c, n1 + c->k[5]);
279 n1 ^= f(c, n2 + c->k[4]);
280 n2 ^= f(c, n1 + c->k[3]);
281 n1 ^= f(c, n2 + c->k[2]);
282 n2 ^= f(c, n1 + c->k[1]);
283 n1 ^= f(c, n2 + c->k[0]);
285 out[0] = (byte) (n2 & 0xff);
286 out[1] = (byte) ((n2 >> 8) & 0xff);
287 out[2] = (byte) ((n2 >> 16) & 0xff);
288 out[3] = (byte) (n2 >> 24);
289 out[4] = (byte) (n1 & 0xff);
290 out[5] = (byte) ((n1 >> 8) & 0xff);
291 out[6] = (byte) ((n1 >> 16) & 0xff);
292 out[7] = (byte) (n1 >> 24);
295 /* Low-level decryption routine. Decrypts one 64-bit block */
296 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
298 register word32 n1, n2; /* As named in the GOST */
299 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
300 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
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 n2 ^= f(c, n1 + c->k[7]);
321 n1 ^= f(c, n2 + c->k[6]);
322 n2 ^= f(c, n1 + c->k[5]);
323 n1 ^= f(c, n2 + c->k[4]);
324 n2 ^= f(c, n1 + c->k[3]);
325 n1 ^= f(c, n2 + c->k[2]);
326 n2 ^= f(c, n1 + c->k[1]);
327 n1 ^= f(c, n2 + c->k[0]);
329 n2 ^= f(c, n1 + c->k[7]);
330 n1 ^= f(c, n2 + c->k[6]);
331 n2 ^= f(c, n1 + c->k[5]);
332 n1 ^= f(c, n2 + c->k[4]);
333 n2 ^= f(c, n1 + c->k[3]);
334 n1 ^= f(c, n2 + c->k[2]);
335 n2 ^= f(c, n1 + c->k[1]);
336 n1 ^= f(c, n2 + c->k[0]);
338 out[0] = (byte) (n2 & 0xff);
339 out[1] = (byte) ((n2 >> 8) & 0xff);
340 out[2] = (byte) ((n2 >> 16) & 0xff);
341 out[3] = (byte) (n2 >> 24);
342 out[4] = (byte) (n1 & 0xff);
343 out[5] = (byte) ((n1 >> 8) & 0xff);
344 out[6] = (byte) ((n1 >> 16) & 0xff);
345 out[7] = (byte) (n1 >> 24);
348 /* Encrypts several blocks in ECB mode */
349 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
352 for (i = 0; i < blocks; i++) {
353 gostcrypt(c, clear, cipher);
359 /* Decrypts several blocks in ECB mode */
360 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
363 for (i = 0; i < blocks; i++) {
364 gostdecrypt(c, cipher, clear);
370 /* Encrypts several full blocks in CFB mode using 8byte IV */
371 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
372 byte * cipher, int blocks)
379 memcpy(cur_iv, iv, 8);
380 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
381 gostcrypt(ctx, cur_iv, gamma);
382 for (j = 0; j < 8; j++) {
383 cur_iv[j] = out[j] = in[j] ^ gamma[j];
388 /* Decrypts several full blocks in CFB mode using 8byte IV */
389 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
390 byte * clear, int blocks)
397 memcpy(cur_iv, iv, 8);
398 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
399 gostcrypt(ctx, cur_iv, gamma);
400 for (j = 0; j < 8; j++) {
401 out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
406 /* Encrypts one block using specified key */
407 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
411 gostcrypt(c, inblock, outblock);
414 /* Set 256 bit key into context */
415 void gost_key(gost_ctx * c, const byte * k)
418 for (i = 0, j = 0; i < 8; i++, j += 4) {
420 k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
425 /* Retrieve 256-bit key from context */
426 void gost_get_key(gost_ctx * c, byte * k)
429 for (i = 0, j = 0; i < 8; i++, j += 4) {
430 k[j] = (byte) (c->k[i] & 0xFF);
431 k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
432 k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
433 k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
437 /* Initalize context. Provides default value for subst_block */
438 void gost_init(gost_ctx * c, const gost_subst_block * b)
441 b = &GostR3411_94_TestParamSet;
446 /* Cleans up key from context */
447 void gost_destroy(gost_ctx * c)
450 for (i = 0; i < 8; i++)
455 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
456 * with substitution blocks and key buffer - 8-byte mac state buffer block
457 * 8-byte block to process.
459 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
461 register word32 n1, n2; /* As named in the GOST */
463 for (i = 0; i < 8; i++) {
464 buffer[i] ^= block[i];
466 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
468 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
470 /* Instead of swapping halves, swap names each round */
472 n2 ^= f(c, n1 + c->k[0]);
473 n1 ^= f(c, n2 + c->k[1]);
474 n2 ^= f(c, n1 + c->k[2]);
475 n1 ^= f(c, n2 + c->k[3]);
476 n2 ^= f(c, n1 + c->k[4]);
477 n1 ^= f(c, n2 + c->k[5]);
478 n2 ^= f(c, n1 + c->k[6]);
479 n1 ^= f(c, n2 + c->k[7]);
481 n2 ^= f(c, n1 + c->k[0]);
482 n1 ^= f(c, n2 + c->k[1]);
483 n2 ^= f(c, n1 + c->k[2]);
484 n1 ^= f(c, n2 + c->k[3]);
485 n2 ^= f(c, n1 + c->k[4]);
486 n1 ^= f(c, n2 + c->k[5]);
487 n2 ^= f(c, n1 + c->k[6]);
488 n1 ^= f(c, n2 + c->k[7]);
490 buffer[0] = (byte) (n1 & 0xff);
491 buffer[1] = (byte) ((n1 >> 8) & 0xff);
492 buffer[2] = (byte) ((n1 >> 16) & 0xff);
493 buffer[3] = (byte) (n1 >> 24);
494 buffer[4] = (byte) (n2 & 0xff);
495 buffer[5] = (byte) ((n2 >> 8) & 0xff);
496 buffer[6] = (byte) ((n2 >> 16) & 0xff);
497 buffer[7] = (byte) (n2 >> 24);
500 /* Get mac with specified number of bits from MAC state buffer */
501 void get_mac(byte * buffer, int nbits, byte * out)
503 int nbytes = nbits >> 3;
504 int rembits = nbits & 7;
505 int mask = rembits ? ((1 < rembits) - 1) : 0;
507 for (i = 0; i < nbytes; i++)
510 out[i] = buffer[i] & mask;
514 * Compute mac of specified length (in bits) from data. Context should be
515 * initialized with key and subst blocks
517 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
518 unsigned int data_len, unsigned char *mac)
520 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
523 for (i = 0; i + 8 <= data_len; i += 8)
524 mac_block(ctx, buffer, data + i);
527 memcpy(buf2, data + i, data_len - i);
528 mac_block(ctx, buffer, buf2);
533 mac_block(ctx, buffer, buf2);
535 get_mac(buffer, mac_len, mac);
539 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
540 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
541 const unsigned char *data, unsigned int data_len,
547 memcpy(buffer, iv, 8);
548 for (i = 0; i + 8 <= data_len; i += 8)
549 mac_block(ctx, buffer, data + i);
552 memcpy(buf2, data + i, data_len - i);
553 mac_block(ctx, buffer, buf2);
558 mac_block(ctx, buffer, buf2);
560 get_mac(buffer, mac_len, mac);
564 /* Implements key meshing algorithm by modifing ctx and IV in place */
565 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
567 unsigned char newkey[32], newiv[8];
568 /* Set static keymeshing key */
569 /* "Decrypt" key with keymeshing key */
570 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
572 gost_key(ctx, newkey);
573 /* Encrypt iv with new key */
574 gostcrypt(ctx, iv, newiv);
575 memcpy(iv, newiv, 8);