1/**********************************************************************
2 *                        gost89.c                                    *
3 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4 *         This file is distributed under the same license as OpenSSL *
5 *                                                                    *
6 *          Implementation of GOST 28147-89 encryption algorithm      *
7 *            No OpenSSL libraries required to compile and use        *
8 *                              this code                             *
9 **********************************************************************/
10#include <string.h>
11#include "gost89.h"
12/* Substitution blocks from RFC 4357
13
14   Note: our implementation of gost 28147-89 algorithm
15   uses S-box matrix rotated 90 degrees counterclockwise, relative to
16   examples given in RFC.
17
18
19*/
20
21/* Substitution blocks from test examples for GOST R 34.11-94*/
22gost_subst_block GostR3411_94_TestParamSet = {
23	{0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC},
24	{0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC},
25	{0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE},
26	{0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2},
27	{0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3},
28	{0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB},
29	{0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9},
30	{0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3}
31	};
32/* Substitution blocks for hash function 1.2.643.2.9.1.6.1  */
33gost_subst_block GostR3411_94_CryptoProParamSet= {
34	{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
35	{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
36	{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
37	{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
38	{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
39	{0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
40	{0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
41	{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
42	} ;
43
44/* Test paramset from GOST 28147 */
45gost_subst_block Gost28147_TestParamSet =
46	{
47	{0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8},
48	{0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD},
49	{0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4},
50	{0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4},
51	{0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8},
52	{0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB},
53	{0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5},
54	{0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6}
55	};
56
57
58
59
60/* 1.2.643.2.2.31.1 */
61gost_subst_block Gost28147_CryptoProParamSetA= {
62	{0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4},
63	{0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE},
64	{0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6},
65	{0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6},
66	{0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6},
67	{0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9},
68	{0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1},
69	{0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5}
70	};
71/* 1.2.643.2.2.31.2 */
72gost_subst_block Gost28147_CryptoProParamSetB=
73	{
74	{0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC},
75	{0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE},
76	{0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5},
77	{0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3},
78	{0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8},
79	{0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4},
80	{0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE},
81	{0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF}
82	};
83/* 1.2.643.2.2.31.3 */
84gost_subst_block Gost28147_CryptoProParamSetC=
85	{
86	{0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8},
87	{0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7},
88	{0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD},
89	{0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7},
90	{0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4},
91	{0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB},
92	{0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3},
93	{0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3}
94	};
95
96/* 1.2.643.2.2.31.4 */
97gost_subst_block Gost28147_CryptoProParamSetD=
98	{
99	{0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE},
100	{0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7},
101	{0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6},
102	{0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1},
103	{0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8},
104	{0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2},
105	{0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1},
106	{0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3}
107	};
108
109
110const byte CryptoProKeyMeshingKey[]={
111	0x69, 0x00, 0x72, 0x22,   0x64, 0xC9, 0x04, 0x23,
112    0x8D, 0x3A, 0xDB, 0x96,   0x46, 0xE9, 0x2A, 0xC4,
113    0x18, 0xFE, 0xAC, 0x94,   0x00, 0xED, 0x07, 0x12,
114    0xC0, 0x86, 0xDC, 0xC2,   0xEF, 0x4C, 0xA9, 0x2B
115	};
116/* Initialization of gost_ctx subst blocks*/
117static void kboxinit(gost_ctx *c, const gost_subst_block *b)
118	{
119	int i;
120
121	for (i = 0; i < 256; i++)
122		{
123		c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
124		c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
125		c->k43[i] = (b->k4[i>>4] <<4  | b->k3 [i &15])<<8;
126		c->k21[i] = b->k2[i>>4] <<4  | b->k1 [i &15];
127
128		}
129	}
130
131/* Part of GOST 28147 algorithm moved into separate function */
132static word32 f(gost_ctx *c,word32 x)
133	{
134	x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
135		c->k43[x>> 8 & 255] | c->k21[x & 255];
136	/* Rotate left 11 bits */
137	return x<<11 | x>>(32-11);
138	}
139/* Low-level encryption routine - encrypts one 64 bit block*/
140void gostcrypt(gost_ctx *c, const byte *in, byte *out)
141	{
142	register word32 n1, n2; /* As named in the GOST */
143	n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
144	n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
145	/* Instead of swapping halves, swap names each round */
146
147	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
148	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
149	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
150	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
151
152	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
153	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
154	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
155	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
156
157	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
158	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
159	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
160	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
161
162	n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
163	n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
164	n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
165	n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
166
167	out[0] = (byte)(n2&0xff);  out[1] = (byte)((n2>>8)&0xff);
168	out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24);
169	out[4] = (byte)(n1&0xff);  out[5] = (byte)((n1>>8)&0xff);
170	out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24);
171	}
172/* Low-level decryption routine. Decrypts one 64-bit block */
173void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
174	{
175	register word32 n1, n2; /* As named in the GOST */
176	n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
177	n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
178
179	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
180	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
181	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
182	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
183
184	n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
185	n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
186	n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
187	n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
188
189	n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
190	n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
191	n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
192	n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
193
194	n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
195	n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
196	n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
197	n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
198
199	out[0] = (byte)(n2&0xff);  out[1] = (byte)((n2>>8)&0xff);
200	out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24);
201	out[4] = (byte)(n1&0xff);  out[5] = (byte)((n1>>8)&0xff);
202	out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24);
203	}
204
205/* Encrypts several blocks in ECB mode */
206void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
207	{
208	int i;
209	for(i=0;i<blocks;i++)
210		{
211		gostcrypt(c,clear,cipher);
212		clear+=8;
213		cipher+=8;
214		}
215	}
216/* Decrypts several blocks in ECB mode */
217void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
218	{
219	int i;
220	for(i=0;i<blocks;i++)
221		{
222		gostdecrypt(c,cipher,clear);
223		clear+=8;
224		cipher+=8;
225		}
226	}
227
228/* Encrypts several full blocks in CFB mode using 8byte IV */
229void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks)
230	{
231	byte cur_iv[8];
232	byte gamma[8];
233	int i,j;
234	const byte *in;
235	byte *out;
236	memcpy(cur_iv,iv,8);
237	for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8)
238		{
239		gostcrypt(ctx,cur_iv,gamma);
240		for (j=0;j<8;j++)
241			{
242			cur_iv[j]=out[j]=in[j]^gamma[j];
243			}
244		}
245	}
246/* Decrypts several full blocks in CFB mode using 8byte IV */
247void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear,  int blocks)
248	{
249	byte cur_iv[8];
250	byte gamma[8];
251	int i,j;
252	const byte *in;
253	byte *out;
254	memcpy(cur_iv,iv,8);
255	for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8)
256		{
257		gostcrypt(ctx,cur_iv,gamma);
258		for (j=0;j<8;j++)
259			{
260			out[j]=(cur_iv[j]=in[j])^gamma[j];
261			}
262		}
263	}
264
265/* Encrypts one block using specified key */
266void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
267	{
268	gost_key(c,key);
269	gostcrypt(c,inblock,outblock);
270	}
271
272/* Set 256 bit  key into context */
273void gost_key(gost_ctx *c, const byte *k)
274	{
275	int i,j;
276	for(i=0,j=0;i<8;i++,j+=4)
277		{
278		c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24);
279		}
280	}
281
282/* Retrieve 256-bit key from context */
283void gost_get_key(gost_ctx *c, byte *k)
284	{
285	int i,j;
286	for(i=0,j=0;i<8;i++,j+=4)
287		{
288		k[j]=(byte)(c->k[i]& 0xFF);
289		k[j+1]=(byte)((c->k[i]>>8 )&0xFF);
290		k[j+2]=(byte)((c->k[i]>>16) &0xFF);
291		k[j+3]=(byte)((c->k[i]>>24) &0xFF);
292		}
293	}
294
295/* Initalize context. Provides default value for subst_block */
296void gost_init(gost_ctx *c, const gost_subst_block *b)
297	{
298	if(!b)
299		{
300		b=&GostR3411_94_TestParamSet;
301		}
302	kboxinit(c,b);
303	}
304
305/* Cleans up key from context */
306void gost_destroy(gost_ctx *c)
307	{
308	int i; for(i=0;i<8;i++) c->k[i]=0;
309	}
310
311/* Compute GOST 28147 mac block
312 *
313 * Parameters
314 *   gost_ctx *c - context initalized with substitution blocks and key
315 *   buffer - 8-byte mac state buffer
316 *   block 8-byte block to process.
317 * */
318void mac_block(gost_ctx *c,byte *buffer,const  byte *block)
319	{
320	register word32 n1, n2; /* As named in the GOST */
321	int i;
322	for (i=0; i<8; i++)
323		{
324		buffer[i]^=block[i];
325		}
326	n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
327	n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24);
328	/* Instead of swapping halves, swap names each round */
329
330	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
331	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
332	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
333	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
334
335	n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
336	n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
337	n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
338	n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
339
340	buffer[0] = (byte)(n1&0xff);  buffer[1] = (byte)((n1>>8)&0xff);
341	buffer[2] = (byte)((n1>>16)&0xff); buffer[3] = (byte)(n1>>24);
342	buffer[4] = (byte)(n2&0xff);  buffer[5] = (byte)((n2>>8)&0xff);
343	buffer[6] = (byte)((n2>>16)&0xff); buffer[7] = (byte)(n2>>24);
344	}
345
346/* Get mac with specified number of bits from MAC state buffer */
347void get_mac(byte *buffer,int nbits,byte *out)
348	{
349	int nbytes= nbits >> 3;
350	int rembits = nbits & 7;
351	int mask =rembits?((1<rembits)-1):0;
352	int i;
353	for (i=0;i<nbytes;i++) out[i]=buffer[i];
354	if (rembits) out[i]=buffer[i]&mask;
355	}
356
357/* Compute mac of specified length (in bits) from data.
358 * Context should be initialized with key and subst blocks */
359int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
360	unsigned int data_len,unsigned char *mac)
361	{
362	byte buffer[8]={0,0,0,0,0,0,0,0};
363	byte buf2[8];
364	unsigned int i;
365	for (i=0;i+8<=data_len;i+=8)
366		mac_block(ctx,buffer,data+i);
367	if (i<data_len)
368		{
369		memset(buf2,0,8);
370		memcpy(buf2,data+i,data_len-i);
371		mac_block(ctx,buffer,buf2);
372		}
373	get_mac(buffer,mac_len,mac);
374	return 1;
375	}
376
377/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
378int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
379	unsigned int data_len,unsigned char *mac)
380	{
381	byte buffer[8];
382	byte buf2[8];
383	unsigned int i;
384	memcpy (buffer,iv,8);
385	for (i=0;i+8<=data_len;i+=8)
386		mac_block(ctx,buffer,data+i);
387	if (i<data_len)
388		{
389		memset(buf2,0,8);
390		memcpy(buf2,data+i,data_len-i);
391		mac_block(ctx,buffer,buf2);
392		}
393	get_mac(buffer,mac_len,mac);
394	return 1;
395	}
396
397/* Implements key meshing algorithm by modifing ctx and IV in place */
398void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv)
399	{
400	unsigned char newkey[32],newiv[8];
401	/* Set static keymeshing key */
402	/* "Decrypt" key with keymeshing key */
403	gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4);
404	/* set new key */
405	gost_key(ctx,newkey);
406	/* Encrypt iv with new key */
407	gostcrypt(ctx,iv,newiv);
408	memcpy(iv,newiv,8);
409	}
410