9b3803d8fdcbfca1e746c05e163a565955f822f7
[openssl.git] / engines / ccgost / gost_crypt.c
1 /**********************************************************************
2 *                          gost_crypt.c                              *
3 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4 *         This file is distributed under the same license as OpenSSL *
5 *                                                                    *
6 *       OpenSSL interface to GOST 28147-89 cipher functions          *
7 *          Requires OpenSSL 0.9.9 for compilation                    *
8 **********************************************************************/
9 #include <string.h>
10 #include "crypt.h"
11 #include "gost89.h"
12 #include <openssl/rand.h>
13 #include "e_gost_err.h"
14 #include "gost_asn1.h"
15 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 
16                         const unsigned char *iv, int enc);
17 #ifdef USE_SSL
18 /* Specialized init functions which set specific parameters */                  
19 static int      gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
20                         const unsigned char *iv, int enc);
21 static int      gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
22                         const unsigned char *iv, int enc);
23 #endif
24 /* Handles block of data in CFB mode */                 
25 static int      gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
26                         const unsigned char *in, unsigned int inl);
27 /* Handles block of data in CNT mode */                 
28 static int      gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
29                         const unsigned char *in, unsigned int inl);
30 /* Cleanup function */                  
31 static int gost_cipher_cleanup(EVP_CIPHER_CTX *);
32 /* set/get cipher parameters */
33 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params);
34 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params);
35 /* Control function */
36 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr);
37
38 EVP_CIPHER cipher_gost = 
39         {
40           NID_id_Gost28147_89,
41           1,/*block_size*/
42           32,/*key_size*/
43           8,/*iv_len - ñèíõðîïîñûëêà*/
44           EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
45                         EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
46           gost_cipher_init,
47           gost_cipher_do_cfb,
48           gost_cipher_cleanup,
49           sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */
50           gost89_set_asn1_parameters,
51           gost89_get_asn1_parameters,
52           gost_cipher_ctl,
53           NULL,
54         };
55
56 #ifdef USE_SSL
57 static EVP_CIPHER cipher_gost_vizircfb = 
58         {
59           NID_undef,
60           1,/*block_size*/
61           32,/*key_size*/
62           8,/*iv_len - ñèíõðîïîñûëêà*/
63           EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
64                         EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
65                 gost_cipher_init_vizir,
66                 gost_cipher_do_cfb,
67                 gost_cipher_cleanup,
68                 sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
69             gost89_set_asn1_parameters,
70             gost89_get_asn1_parameters,
71             gost_cipher_ctl,
72           NULL,
73         };
74
75 static EVP_CIPHER cipher_gost_cpacnt = 
76         {
77           NID_undef,
78           1,/*block_size*/
79           32,/*key_size*/
80           8,/*iv_len - ñèíõðîïîñûëêà*/
81           EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING |
82                         EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
83           gost_cipher_init_cpa,
84           gost_cipher_do_cnt,
85           gost_cipher_cleanup,
86                 sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
87           gost89_set_asn1_parameters,
88           gost89_get_asn1_parameters,
89           gost_cipher_ctl,
90           NULL,
91         };
92 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
93 /* Init functions which set specific parameters */
94 static int gost_imit_init_vizir(EVP_MD_CTX *ctx);
95 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
96 /* process block of data */
97 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
98 /* Return computed value */
99 static int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md);
100 /* Copies context */
101 static int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from);
102 static int gost_imit_cleanup(EVP_MD_CTX *ctx);
103 /* Control function, knows how to set MAC key.*/
104 static int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr);
105
106 EVP_MD imit_gost_vizir =
107         {
108         NID_undef,
109         NID_undef,
110         4,
111         EVP_MD_FLAG_NEEDS_KEY,
112         gost_imit_init_vizir,
113         gost_imit_update,
114         gost_imit_final,
115         gost_imit_copy,
116         gost_imit_cleanup,
117         gost_imit_ctrl,
118         NULL,
119         NULL,
120         {0,0,0,0,0},
121         8,
122         sizeof(struct ossl_gost_imit_ctx) 
123         };
124
125 EVP_MD imit_gost_cpa =
126         {
127         NID_undef,
128         NID_undef,
129         4,
130         EVP_MD_FLAG_NEEDS_KEY,
131         gost_imit_init_cpa,
132         gost_imit_update,
133         gost_imit_final,
134         gost_imit_copy,
135         gost_imit_cleanup,
136         gost_imit_ctrl,
137         NULL,
138         NULL,
139         {0,0,0,0,0},
140         8,
141         sizeof(struct ossl_gost_imit_ctx) 
142         };
143
144 #endif
145 /* 
146 * Correspondence between gost parameter OIDs and substitution blocks
147 * NID field is filed by register_gost_NID function in engine.c
148 * upon engine initialization
149 */
150
151 struct gost_cipher_info gost_cipher_list[]={
152 /* NID */  /* Subst block */          /* Key meshing*/
153 /*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/
154 {NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0},
155 {NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1},
156 {NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
157 {NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
158 {NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
159 {NID_undef,NULL,0}
160 };      
161
162 /*  get encryption parameters from crypto network settings
163 FIXME For now we use environment var CRYPT_PARAMS as place to 
164 store these settings. Actually, it is better to use engine control   command, read from configuration file to set them */
165 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) {
166 int nid;
167 struct gost_cipher_info *param;
168 if (!obj) {
169         const char * params = getenv("CRYPT_PARAMS");
170         if (!params || !strlen(params)) 
171                 return &gost_cipher_list[0];
172
173         nid = OBJ_txt2nid(params);
174         if (nid == NID_undef) {
175                 GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
176                                 GOST_R_INVALID_CIPHER_PARAM_OID);
177                 return NULL;
178         }       
179 } else {
180         nid= OBJ_obj2nid(obj);
181 }
182 for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid; 
183                 param++);
184 if (!param->sblock) {
185         GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS);
186         return NULL;
187
188 }       
189 return param;
190
191 }
192 /* Sets cipher param from paramset NID. */
193 int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid) {
194 const struct gost_cipher_info *param;
195 param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid)));
196 if (!param) return 0;
197         
198 c->paramNID = param->nid;
199 c->key_meshing=param->key_meshing;
200 c->count=0;
201 gost_init(&(c->cctx), param->sblock);
202 return 1;
203 }
204 /* Initializes EVP_CIPHER_CTX by paramset NID */
205 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key,
206         const unsigned char *iv, int enc, int paramNID,int mode) {
207 struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
208 if (!gost_cipher_set_param(c,paramNID)) return 0;
209 if (key) gost_key(&(c->cctx),key);
210 if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
211 memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
212 return 1;
213 }       
214
215 /* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */
216 int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
217                 const unsigned char *iv, int enc) {
218 struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
219 gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
220 c->key_meshing=1;
221 c->count=0;
222 gost_key(&(c->cctx),key);
223 if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
224 memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
225 return 1;
226 }       
227 /* Initializes EVP_CIPHER_CTX with fixed vizir paramset */
228 int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
229                 const unsigned char *iv, int enc) {
230 struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
231 gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
232 c->key_meshing=0;
233 c->count=0;
234 gost_key(&(c->cctx),key);
235
236 if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
237 memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
238 return 1;
239 }       
240
241 /* Initializes EVP_CIPHER_CTX with default values */
242 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
243                 const unsigned char *iv, int enc) {
244 return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
245 }       
246 /* Wrapper around gostcrypt function from gost89.c which perform
247 * key meshing when nesseccary 
248 */
249 static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) {
250         struct ossl_gost_cipher_ctx *c = ctx;
251         if (c->count&&c->key_meshing && c->count%1024==0) {
252                 cryptopro_key_meshing(&(c->cctx),iv);
253         }       
254         gostcrypt(&(c->cctx),iv,buf);
255         c->count+=8;
256 }
257
258 static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) {
259 struct ossl_gost_cipher_ctx *c = ctx;
260 word32 g,go;
261 unsigned char buf1[8];
262 if (c->count && c->key_meshing && c->count %1024 ==0) {
263         cryptopro_key_meshing(&(c->cctx),iv);
264 }
265 if (c->count==0) {
266 gostcrypt(&(c->cctx),iv,buf1);
267 } else {
268         memcpy(buf1,iv,8);
269 }       
270         g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24);
271         g += 0x01010101;
272         buf1[0]=g&0xff; buf1[1]=(g>>8)&0xff; buf1[2]=(g>>16)&0xff; buf1[3]=(g>>24)&0xff;
273         g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|(buf1[7]<<24);
274         go = g;
275         g += 0x01010104;
276         if (go > g)      /*  overflow*/
277                 g++;
278         buf1[4]=g&0xff; buf1[5]=(g>>8)&0xff; buf1[6]=(g>>16)&0xff; buf1[7]=(g>>24)&0xff;
279         memcpy(iv,buf1,8);
280         gostcrypt(&(c->cctx),buf1,buf);
281 c->count +=8;
282 }
283
284 /* GOST encryption in CFB mode */
285 int     gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
286                 const unsigned char *in, unsigned int inl) {
287 const unsigned char *in_ptr=in;
288 unsigned char *out_ptr=out;
289 int i=0;
290 int j;
291 /* process partial block if any */
292 if (ctx->num) 
293 {
294         for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 
295         {
296                 if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr;
297                 *out_ptr=ctx->buf[j]^(*in_ptr);
298                 if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
299         }       
300         if (j==8) {
301                 memcpy(ctx->iv,ctx->buf+8,8);
302                 ctx->num=0;
303         } else {
304                 ctx->num=j;
305                 return 1;
306         }       
307 }       
308
309 for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) {
310         /*block cipher current iv */
311         gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
312         /*xor next block of input text with it and output it*/
313         /*output this block */
314         if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
315         for (j=0;j<8;j++) {
316                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
317         }       
318         /* Encrypt */
319         /* Next iv is next block of cipher text*/
320         if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
321 }
322 /* Process rest of buffer */
323 if (i<inl) {
324         gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
325         if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j);
326         for (j=0;i<inl;j++,i++) {
327                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
328         }                       
329         ctx->num = j;
330         if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
331 } else {
332         ctx->num = 0;
333 }       
334 return 1;
335 }       
336 int     gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
337                 const unsigned char *in, unsigned int inl) {
338 const unsigned char *in_ptr=in;
339 unsigned char *out_ptr=out;
340 int i=0;
341 int j;
342 /* process partial block if any */
343 if (ctx->num) 
344 {
345         for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 
346         {
347                 *out_ptr=ctx->buf[j]^(*in_ptr);
348         }       
349         if (j==8) {
350                 ctx->num=0;
351         } else {
352                 ctx->num=j;
353                 return 1;
354         }       
355 }       
356
357 for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) {
358         /*block cipher current iv */
359         /* Encrypt */
360         gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
361         /*xor next block of input text with it and output it*/
362         /*output this block */
363         for (j=0;j<8;j++) {
364                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
365         }       
366 }
367 /* Process rest of buffer */
368 if (i<inl) {
369         gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
370         for (j=0;i<inl;j++,i++) {
371                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
372         }                       
373         ctx->num = j;
374 } else {
375         ctx->num = 0;
376 }       
377 return 1;
378 }       
379 /* Cleaning up of EVP_CIPHER_CTX */
380 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) 
381 {
382 gost_destroy((gost_ctx *)ctx->cipher_data);
383 return 1;
384
385 }       
386 /* Control function for gost cipher */
387 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr)
388 {
389 switch (type)
390 {
391         case EVP_CTRL_RAND_KEY:
392                 {
393                                 if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
394                                 {
395                                         GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_ERROR);
396                                         return -1;
397                                 }
398                                 break;
399                         }
400         default:
401                                         GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
402                         return -1;
403 }
404 return 1;
405 }
406
407 /* Set cipher parameters from ASN1 structure */
408 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
409 {
410 int len=0;
411 unsigned char *buf=NULL;
412 unsigned char *p=NULL;
413 struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
414 GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
415 ASN1_OCTET_STRING *os = NULL;
416 if (!gcp) {
417         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
418         return 0;
419 }
420 if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) {
421         GOST_CIPHER_PARAMS_free(gcp);
422         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
423         return 0;
424 }
425 ASN1_OBJECT_free(gcp->enc_param_set);
426 gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
427
428 len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
429 p = buf = (unsigned char*)OPENSSL_malloc(len);
430 if (!buf) {
431         GOST_CIPHER_PARAMS_free(gcp);
432         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
433         return 0;
434 }
435 i2d_GOST_CIPHER_PARAMS(gcp, &p);
436 GOST_CIPHER_PARAMS_free(gcp);
437
438 os = ASN1_OCTET_STRING_new();
439
440 if(!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
441         OPENSSL_free(buf);
442         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
443         return 0;
444 }
445 OPENSSL_free(buf);
446
447 ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
448 return 1;
449 }
450 /* Store parameters into ASN1 structure */
451 int  gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
452 {
453 int ret = -1;
454 int len; 
455 GOST_CIPHER_PARAMS *gcp = NULL;
456 unsigned char *p = params->value.sequence->data;
457 struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
458 if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
459         return ret;
460 }
461
462 gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
463                 params->value.sequence->length);
464
465 len = gcp->iv->length;
466 if (len != ctx->cipher->iv_len) {
467         GOST_CIPHER_PARAMS_free(gcp);
468         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
469                         GOST_R_INVALID_IV_LENGTH);
470         return -1;
471 }
472 if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set))) {
473         GOST_CIPHER_PARAMS_free(gcp);
474         return -1;
475 }
476 memcpy(ctx->oiv, gcp->iv->data, len);
477
478 GOST_CIPHER_PARAMS_free(gcp);
479
480 return 1;
481         
482 }
483
484 #ifdef USE_SSL
485
486 int gost_imit_init_vizir(EVP_MD_CTX *ctx) {
487 struct ossl_gost_imit_ctx *c = ctx->md_data;
488 memset(c,0,sizeof(struct ossl_gost_imit_ctx));
489 gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
490 return 1;
491 }
492 int gost_imit_init_cpa(EVP_MD_CTX *ctx) {
493 struct ossl_gost_imit_ctx *c = ctx->md_data;
494 memset(c,0,sizeof(struct ossl_gost_imit_ctx));
495 c->key_meshing=1;
496 gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
497 return 1;
498 }
499
500 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,unsigned char *data)
501 {
502         char buffer[8];
503         /* We are using local buffer for iv because CryptoPro doesn't 
504          * interpret internal state of MAC algorithm as iv during keymeshing
505          * (but does initialize internal state from iv in key transport
506          */
507         if (c->key_meshing&& c->count && c->count %1024 ==0) {
508                 cryptopro_key_meshing(&(c->cctx),buffer);
509         }
510         mac_block(&(c->cctx),c->buffer,data);
511         c->count +=8;
512 }
513
514 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
515         struct ossl_gost_imit_ctx *c = ctx->md_data;
516         const unsigned char *p = data;
517         size_t bytes = count,i;
518         if (!(c->key_set)) return 0;
519         if (c->bytes_left) {
520                 for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++) {
521                         c->partial_block[i]=*p;
522                 }
523                 if (i==8) {
524                         mac_block_mesh(c,c->partial_block);
525                 } else {
526                         c->bytes_left = i;
527                         return 1;
528                 }               
529         }       
530         while (bytes>8) {
531                 mac_block_mesh(c,p);
532                 p+=8;
533                 bytes-=8;
534         }
535         if (bytes>0) {
536                 memcpy(c->partial_block,p,bytes);
537                 c->bytes_left=bytes;
538         }       
539         return 1;
540 }
541
542 int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) {
543         struct ossl_gost_imit_ctx *c = ctx->md_data;
544         if (c->bytes_left) {
545                 int i;
546                 for (i=c->bytes_left;i<8;i++) {
547                         c->partial_block[i]=0;
548                 }
549                 mac_block_mesh(c,c->partial_block);
550         }
551         get_mac(c->buffer,32,md);
552         return 1;
553 }
554 int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr) {
555         switch (type) {
556             case EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH:
557                        *((unsigned int*)(ptr)) = 32;
558                            return 1;
559             case EVP_MD_CTRL_SET_KEY:
560            {
561                     gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr) ;
562                         ((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1;
563
564                 }
565                 default:
566                         return 0;
567         }               
568 }
569 int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) {
570         memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx));
571         return 1;
572 }
573 /* Clean up imit ctx */
574 int gost_imit_cleanup(EVP_MD_CTX *ctx) {
575         memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx));
576         return 1;
577         
578 }
579 #endif