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