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