~andersk/ubuntu/oneiric/openssl/spurious-reboot

« back to all changes in this revision

Viewing changes to engines/ccgost/gost_crypt.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2010-12-12 15:37:21 UTC
  • mto: (1.2.1 upstream) (11.2.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 55.
  • Revision ID: james.westby@ubuntu.com-20101212153721-mfw51stum5hwztpd
Tags: upstream-1.0.0c
ImportĀ upstreamĀ versionĀ 1.0.0c

Show diffs side-by-side

added added

removed removed

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