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