GOST public key algorithm ENGINE donated to the OpenSSL by Cryptocom.
[oweals/openssl.git] / engines / ccgost / gost89.c
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*/
22 gost_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  */
33 gost_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 */
45 gost_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 */
61 gost_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 */
72 gost_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 */
84 gost_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 */ 
97 gost_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
110 const 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*/
117 void kboxinit(gost_ctx *c, const gost_subst_block *b) { 
118         int i; 
119         
120         for (i = 0; i < 256; i++) {
121                 c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
122                 c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
123                 c->k43[i] = (b->k4[i>>4] <<4  | b->k3 [i &15])<<8;
124                 c->k21[i] = b->k2[i>>4] <<4  | b->k1 [i &15];
125
126         }
127 }
128
129 /* Part of GOST 28147 algorithm moved into separate function */
130 static word32 
131 f(gost_ctx *c,word32 x) 
132 { x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]| 
133           c->k43[x>> 8 & 255] | c->k21[x & 255]; 
134           /* Rotate left 11 bits */ 
135           return x<<11 | x>>(32-11);
136 }
137 /* Low-level encryption routine - encrypts one 64 bit block*/
138 void gostcrypt(gost_ctx *c, const byte *in, byte *out)
139
140   register word32 n1, n2; /* As named in the GOST */ 
141   n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 
142   n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 
143   /* Instead of swapping halves, swap names each round */ 
144          
145   n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 
146   n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 
147   n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 
148   n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 
149   
150   n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
151   n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
152   n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
153   n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
154                                
155   n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
156   n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
157   n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
158   n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
159                                
160   n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
161   n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
162   n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
163   n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
164  
165   out[0] = (n2&0xff);  out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24; 
166   out[4] = (n1&0xff);  out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
167
168 /* Low-level decryption routine. Decrypts one 64-bit block */
169 void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
170
171         register word32 n1, n2; /* As named in the GOST */ 
172         n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 
173         n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 
174         
175         n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 
176         n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 
177         n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
178         n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 
179         
180         n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
181         n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
182         n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
183         n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
184         
185         n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
186         n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
187         n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
188         n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
189         
190         n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
191         n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
192         n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
193         n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
194         out[0] = (n2&0xff);  out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
195         out[4] = (n1&0xff);  out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
196
197
198 /* Encrypts several blocks in ECB mode */
199 void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
200
201         int i; 
202         for(i=0;i<blocks;i++){ 
203                 gostcrypt(c,clear,cipher); 
204                 clear+=8;
205                 cipher+=8;
206         }
207 }
208 /* Decrypts several blocks in ECB mode */
209 void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
210
211         int i; 
212         for(i=0;i<blocks;i++) { 
213                 gostdecrypt(c,cipher,clear); 
214                 clear+=8; 
215                 cipher+=8;
216         }
217
218 }
219
220 /* Encrypts several full blocks in CFB mode using 8byte IV */
221 void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) {
222         byte cur_iv[8];
223         byte gamma[8];
224         int i,j;
225         const byte *in;
226         byte *out;
227         memcpy(cur_iv,iv,8);
228         for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) {
229                 gostcrypt(ctx,cur_iv,gamma);
230                 for (j=0;j<8;j++) {
231                         cur_iv[j]=out[j]=in[j]^gamma[j];
232                 }
233         }       
234
235 }       
236 /* Decrypts several full blocks in CFB mode using 8byte IV */
237 void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear,  int blocks) {
238         byte cur_iv[8];
239         byte gamma[8];
240         int i,j;
241         const byte *in;
242         byte *out;
243         memcpy(cur_iv,iv,8);
244         for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) {
245                 gostcrypt(ctx,cur_iv,gamma);
246                 for (j=0;j<8;j++) {
247                         out[j]=(cur_iv[j]=in[j])^gamma[j];
248                 }
249         }       
250 }       
251
252 /* Encrypts one block using specified key */
253 void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock) 
254 {
255         gost_key(c,key);
256         gostcrypt(c,inblock,outblock);
257
258 }
259 /* Set 256 bit  key into context */
260 void gost_key(gost_ctx *c, const byte *k) 
261
262         int i,j; 
263         for(i=0,j=0;i<8;i++,j+=4) {
264                 c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24);
265         }               
266
267 /* Retrieve 256-bit key from context */
268 void gost_get_key(gost_ctx *c, byte *k) 
269 {
270         int i,j; 
271         for(i=0,j=0;i<8;i++,j+=4) {
272                 k[j]=c->k[i]& 0xFF;
273                 k[j+1]=(c->k[i]>>8 )&0xFF;
274                 k[j+2]=(c->k[i]>>16) &0xFF;
275                 k[j+3]=(c->k[i]>>24) &0xFF;
276         }               
277
278 }
279 /* Initalize context. Provides default value for subst_block */
280 void gost_init(gost_ctx *c, const gost_subst_block *b)
281 {       
282         if(!b) {
283                 b=&GostR3411_94_TestParamSet;
284         }       
285         kboxinit(c,b); 
286
287 /* Cleans up key from context */
288 void gost_destroy(gost_ctx *c)
289
290         int i; for(i=0;i<8;i++) c->k[i]=0; 
291
292
293 /* Compute GOST 28147 mac block 
294  * 
295  * Parameters
296  *   gost_ctx *c - context initalized with substitution blocks and key
297  *   buffer - 8-byte mac state buffer
298  *   block 8-byte block to process.
299  * */
300 void mac_block(gost_ctx *c,byte *buffer,const  byte *block) {
301         
302   register word32 n1, n2; /* As named in the GOST */ 
303   int i;
304   for (i=0; i<8; i++) {
305           buffer[i]^=block[i];
306   }       
307   n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24); 
308   n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24); 
309   /* Instead of swapping halves, swap names each round */ 
310          
311   n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 
312   n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 
313   n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 
314   n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 
315   
316   n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
317   n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
318   n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
319   n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
320
321         buffer[0] = (n1&0xff);  buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24;
322         buffer[4] = (n2&0xff);  buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24;
323 }
324
325 /* Get mac with specified number of bits from MAC state buffer */
326 void get_mac(byte *buffer,int nbits,byte *out) {
327         int nbytes= nbits >> 3;
328         int rembits = nbits & 7;
329         int mask =rembits?((1<rembits)-1):0;
330         int i;
331         for (i=0;i<nbytes;i++) out[i]=buffer[i];
332         if (rembits) out[i]=buffer[i]&mask;
333 }       
334
335 /* Compute mac of specified length (in bits) from data. 
336  * Context should be initialized with key and subst blocks */
337 int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
338                 unsigned int data_len,unsigned char *mac) 
339 {
340         byte buffer[8]={0,0,0,0,0,0,0,0};
341         byte buf2[8];
342         int i;
343         for (i=0;i+8<=data_len;i+=8) 
344                 mac_block(ctx,buffer,data+i);
345         if (i<data_len) {
346                 memset(buf2,0,8);
347                 memcpy(buf2,data+i,data_len-i);
348                 mac_block(ctx,buffer,buf2);
349         }       
350         get_mac(buffer,mac_len,mac);
351         return 1;
352 }
353 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
354 int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
355                 unsigned int data_len,unsigned char *mac) 
356 {
357         byte buffer[8];
358         byte buf2[8];
359         int i;
360         memcpy (buffer,iv,8);
361         for (i=0;i+8<=data_len;i+=8) 
362                 mac_block(ctx,buffer,data+i);
363         if (i<data_len) {
364                 memset(buf2,0,8);
365                 memcpy(buf2,data+i,data_len-i);
366                 mac_block(ctx,buffer,buf2);
367         }       
368         get_mac(buffer,mac_len,mac);
369         return 1;
370 }
371
372 /* Implements key meshing algorithm by modifing ctx and IV in place */
373 void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) {
374         unsigned char newkey[32],newiv[8];
375         /* Set static keymeshing key */
376         /* "Decrypt" key with keymeshing key */
377         gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4);
378         /* set new key */
379         gost_key(ctx,newkey);
380         /* Encrypt iv with new key */
381         gostcrypt(ctx,iv,newiv);
382         memcpy(iv,newiv,8);
383 }