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