OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
gost89.c
Go to the documentation of this file.
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*/
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 */
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 */
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 */
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 */
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 */
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 */
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 
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*/
117 static 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 */
132 static 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*/
140 void 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 */
173 void 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 */
206 void 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 */
217 void 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 */
229 void 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 */
247 void 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 */
266 void 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 */
273 void 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 */
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 */
297  {
298  if(!b)
299  {
301  }
302  kboxinit(c,b);
303  }
304 
305 /* Cleans up key from context */
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  * */
318 void 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 */
347 void 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 */
359 int 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 */
378 int 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 */
398 void 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  }