04b1e555c2fb0e6502314588562878a9b7412c8e
[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 static int      gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
17         const unsigned char *iv, int enc);
18 #ifdef USE_SSL
19 /* Specialized init functions which set specific parameters */                  
20 static int      gost_cipher_init_vizir(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 EVP_CIPHER cipher_gost_cpacnt = 
56         {
57         NID_gost89_cnt,
58         1,/*block_size*/
59         32,/*key_size*/
60         8,/*iv_len - ñèíõðîïîñûëêà*/
61         EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING |
62         EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
63         gost_cipher_init_cpa,
64         gost_cipher_do_cnt,
65         gost_cipher_cleanup,
66         sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
67         gost89_set_asn1_parameters,
68         gost89_get_asn1_parameters,
69         gost_cipher_ctl,
70         NULL,
71         };
72
73 #ifdef USE_SSL
74 static EVP_CIPHER cipher_gost_vizircfb = 
75         {
76         NID_undef,
77         1,/*block_size*/
78         32,/*key_size*/
79         8,/*iv_len - ñèíõðîïîñûëêà*/
80         EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
81         EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
82         gost_cipher_init_vizir,
83         gost_cipher_do_cfb,
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
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         {
153 /* NID */  /* Subst block */          /* Key meshing*/
154 /*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/
155         {NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0},
156         {NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1},
157         {NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
158         {NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
159         {NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
160         {NID_id_Gost28147_89_TestParamSet,&Gost28147_TestParamSet,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 static 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 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
230         const unsigned char *iv, int enc)
231         {
232         struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
233         gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
234         c->key_meshing=1;
235         c->count=0;
236         gost_key(&(c->cctx),key);
237         if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
238         memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
239         return 1;
240         }
241 #ifdef USE_SSL
242 /* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */
243
244 /* Initializes EVP_CIPHER_CTX with fixed vizir paramset */
245 static int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
246         const unsigned char *iv, int enc)
247         {
248         struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
249         gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
250         c->key_meshing=0;
251         c->count=0;
252         gost_key(&(c->cctx),key);
253
254         if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
255         memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
256         return 1;
257         }       
258 #endif  /* def USE_SSL */
259
260 /* Initializes EVP_CIPHER_CTX with default values */
261 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
262         const unsigned char *iv, int enc)
263         {
264         return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
265         }       
266 /* Wrapper around gostcrypt function from gost89.c which perform
267  * key meshing when nesseccary 
268  */
269 static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf)
270         {
271         struct ossl_gost_cipher_ctx *c = ctx;
272         if (c->count&&c->key_meshing && c->count%1024==0)
273                 {
274                 cryptopro_key_meshing(&(c->cctx),iv);
275                 }       
276         gostcrypt(&(c->cctx),iv,buf);
277         c->count+=8;
278         }
279
280 static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf)
281         {
282         struct ossl_gost_cipher_ctx *c = ctx;
283         word32 g,go;
284         unsigned char buf1[8];
285         if (c->count && c->key_meshing && c->count %1024 ==0)
286                 {
287                 cryptopro_key_meshing(&(c->cctx),iv);
288                 }
289         if (c->count==0)
290                 {
291                 gostcrypt(&(c->cctx),iv,buf1);
292                 }
293         else
294                 {
295                 memcpy(buf1,iv,8);
296                 }       
297         g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24);
298         g += 0x01010101;
299         buf1[0]=g&0xff; buf1[1]=(g>>8)&0xff; buf1[2]=(g>>16)&0xff; buf1[3]=(g>>24)&0xff;
300         g = buf1[4]|(buf1[5]<<8)|(buf1[6]<<16)|(buf1[7]<<24);
301         go = g;
302         g += 0x01010104;
303         if (go > g)      /*  overflow*/
304                 g++;
305         buf1[4]=g&0xff; buf1[5]=(g>>8)&0xff; buf1[6]=(g>>16)&0xff; buf1[7]=(g>>24)&0xff;
306         memcpy(iv,buf1,8);
307         gostcrypt(&(c->cctx),buf1,buf);
308         c->count +=8;
309         }
310
311 /* GOST encryption in CFB mode */
312 int     gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
313         const unsigned char *in, unsigned int inl)
314         {
315         const unsigned char *in_ptr=in;
316         unsigned char *out_ptr=out;
317         int i=0;
318         int j=0;
319 /* process partial block if any */
320         if (ctx->num) 
321                 {
322                 for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 
323                         {
324                         if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr;
325                         *out_ptr=ctx->buf[j]^(*in_ptr);
326                         if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
327                         }       
328                 if (j==8)
329                         {
330                         memcpy(ctx->iv,ctx->buf+8,8);
331                         ctx->num=0;
332                         }
333                 else
334                         {
335                         ctx->num=j;
336                         return 1;
337                         }       
338                 }       
339
340         for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
341                 {
342                 /*block cipher current iv */
343                 gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
344                 /*xor next block of input text with it and output it*/
345                 /*output this block */
346                 if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
347                 for (j=0;j<8;j++)
348                         {
349                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
350                         }       
351                 /* Encrypt */
352                 /* Next iv is next block of cipher text*/
353                 if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
354                 }
355 /* Process rest of buffer */
356         if (i<inl)
357                 {
358                 gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
359                 if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j);
360                 for (j=0;i<inl;j++,i++)
361                         {
362                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
363                         }                       
364                 ctx->num = j;
365                 if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
366                 }
367         else
368                 {
369                 ctx->num = 0;
370                 }       
371         return 1;
372         }
373
374 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
375         const unsigned char *in, unsigned int inl)
376         {
377         const unsigned char *in_ptr=in;
378         unsigned char *out_ptr=out;
379         int i=0;
380         int j;
381 /* process partial block if any */
382         if (ctx->num) 
383                 {
384                 for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) 
385                         {
386                         *out_ptr=ctx->buf[j]^(*in_ptr);
387                         }       
388                 if (j==8)
389                         {
390                         ctx->num=0;
391                         }
392                 else
393                         {
394                         ctx->num=j;
395                         return 1;
396                         }       
397                 }       
398
399         for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
400                 {
401                 /*block cipher current iv */
402                 /* Encrypt */
403                 gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
404                 /*xor next block of input text with it and output it*/
405                 /*output this block */
406                 for (j=0;j<8;j++)
407                         {
408                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
409                         }       
410                 }
411 /* Process rest of buffer */
412         if (i<inl)
413                 {
414                 gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
415                 for (j=0;i<inl;j++,i++)
416                         {
417                         out_ptr[j]=ctx->buf[j]^in_ptr[j];
418                         }                       
419                 ctx->num = j;
420                 }
421         else
422                 {
423                 ctx->num = 0;
424                 }       
425         return 1;
426         }
427
428 /* Cleaning up of EVP_CIPHER_CTX */
429 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) 
430         {
431         gost_destroy((gost_ctx *)ctx->cipher_data);
432         ctx->app_data = NULL;
433         return 1;
434         }       
435
436 /* Control function for gost cipher */
437 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr)
438         {
439         switch (type)
440                 {
441                 case EVP_CTRL_RAND_KEY:
442                 {
443                 if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
444                         {
445                         GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_ERROR);
446                         return -1;
447                         }
448                 break;
449                 }
450                 default:
451                         GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
452                         return -1;
453                 }
454         return 1;
455         }
456
457 /* Set cipher parameters from ASN1 structure */
458 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
459         {
460         int len=0;
461         unsigned char *buf=NULL;
462         unsigned char *p=NULL;
463         struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
464         GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
465         ASN1_OCTET_STRING *os = NULL;
466         if (!gcp)
467                 {
468                 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
469                 return 0;
470                 }
471         if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len))
472                 {
473                 GOST_CIPHER_PARAMS_free(gcp);
474                 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
475                 return 0;
476                 }
477         ASN1_OBJECT_free(gcp->enc_param_set);
478         gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
479
480         len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
481         p = buf = (unsigned char*)OPENSSL_malloc(len);
482         if (!buf)
483                 {
484                 GOST_CIPHER_PARAMS_free(gcp);
485                 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
486                 return 0;
487                 }
488         i2d_GOST_CIPHER_PARAMS(gcp, &p);
489         GOST_CIPHER_PARAMS_free(gcp);
490
491         os = ASN1_OCTET_STRING_new();
492
493         if(!os || !ASN1_OCTET_STRING_set(os, buf, len))
494                 {
495                 OPENSSL_free(buf);
496                 GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
497                 return 0;
498                 }
499         OPENSSL_free(buf);
500
501         ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
502         return 1;
503         }
504
505 /* Store parameters into ASN1 structure */
506 int  gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
507         {
508         int ret = -1;
509         int len; 
510         GOST_CIPHER_PARAMS *gcp = NULL;
511         unsigned char *p = params->value.sequence->data;
512         struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
513         if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE)
514                 {
515                 return ret;
516                 }
517
518         gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
519                 params->value.sequence->length);
520
521         len = gcp->iv->length;
522         if (len != ctx->cipher->iv_len)
523                 {
524                 GOST_CIPHER_PARAMS_free(gcp);
525                 GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
526                         GOST_R_INVALID_IV_LENGTH);
527                 return -1;
528                 }
529         if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set)))
530                 {
531                 GOST_CIPHER_PARAMS_free(gcp);
532                 return -1;
533                 }
534         memcpy(ctx->oiv, gcp->iv->data, len);
535
536         GOST_CIPHER_PARAMS_free(gcp);
537
538         return 1;
539         }
540
541 #ifdef USE_SSL
542
543 int gost_imit_init_vizir(EVP_MD_CTX *ctx)
544         {
545         struct ossl_gost_imit_ctx *c = ctx->md_data;
546         memset(c,0,sizeof(struct ossl_gost_imit_ctx));
547         gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
548         return 1;
549         }
550
551 int gost_imit_init_cpa(EVP_MD_CTX *ctx)
552         {
553         struct ossl_gost_imit_ctx *c = ctx->md_data;
554         memset(c,0,sizeof(struct ossl_gost_imit_ctx));
555         c->key_meshing=1;
556         gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
557         return 1;
558         }
559
560 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,unsigned char *data)
561         {
562         char buffer[8];
563         /* We are using local buffer for iv because CryptoPro doesn't 
564          * interpret internal state of MAC algorithm as iv during keymeshing
565          * (but does initialize internal state from iv in key transport
566          */
567         if (c->key_meshing&& c->count && c->count %1024 ==0)
568                 {
569                 cryptopro_key_meshing(&(c->cctx),buffer);
570                 }
571         mac_block(&(c->cctx),c->buffer,data);
572         c->count +=8;
573         }
574
575 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
576         {
577         struct ossl_gost_imit_ctx *c = ctx->md_data;
578         const unsigned char *p = data;
579         size_t bytes = count,i;
580         if (!(c->key_set)) return 0;
581         if (c->bytes_left)
582                 {
583                 for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++)
584                         {
585                         c->partial_block[i]=*p;
586                         }
587                 if (i==8)
588                         {
589                         mac_block_mesh(c,c->partial_block);
590                         }
591                 else
592                         {
593                         c->bytes_left = i;
594                         return 1;
595                         }               
596                 }       
597         while (bytes>8)
598                 {
599                 mac_block_mesh(c,p);
600                 p+=8;
601                 bytes-=8;
602                 }
603         if (bytes>0)
604                 {
605                 memcpy(c->partial_block,p,bytes);
606                 c->bytes_left=bytes;
607                 }       
608         return 1;
609         }
610
611 int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
612         {
613         struct ossl_gost_imit_ctx *c = ctx->md_data;
614         if (c->bytes_left)
615                 {
616                 int i;
617                 for (i=c->bytes_left;i<8;i++)
618                         {
619                         c->partial_block[i]=0;
620                         }
621                 mac_block_mesh(c,c->partial_block);
622                 }
623         get_mac(c->buffer,32,md);
624         return 1;
625         }
626
627 int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr)
628         {
629         switch (type)
630                 {
631                 case EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH:
632                         *((unsigned int*)(ptr)) = 32;
633                         return 1;
634                 case EVP_MD_CTRL_SET_KEY:
635                 {
636                 gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr)     ;
637                 ((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1;
638
639                 }
640                 default:
641                         return 0;
642                 }               
643         }
644
645 int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
646         {
647         memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx));
648         return 1;
649         }
650
651 /* Clean up imit ctx */
652 int gost_imit_cleanup(EVP_MD_CTX *ctx)
653         {
654         memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx));
655         return 1;
656         }
657
658 #endif