]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_crypt.c
Formatting fix
[openssl-gost/engine.git] / 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/err.h>
12 #include <openssl/rand.h>
13 #include "e_gost_err.h"
14 #include "gost_lcl.h"
15
16 #if !defined(CCGOST_DEBUG) && !defined(DEBUG)
17 # ifndef NDEBUG
18 #  define NDEBUG
19 # endif
20 #endif
21 #include <assert.h>
22
23 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
24                             const unsigned char *iv, int enc);
25 static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
26                                 const unsigned char *iv, int enc);
27 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
28                                 const unsigned char *iv, int enc);
29 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
30                                   const unsigned char *key,
31                                   const unsigned char *iv, int enc);
32 /* Handles block of data in CFB mode */
33 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
34                               const unsigned char *in, size_t inl);
35 /* Handles block of data in CBC mode */
36 static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
37                               const unsigned char *in, size_t inl);
38 /* Handles block of data in CNT mode */
39 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
40                               const unsigned char *in, size_t inl);
41 /* Cleanup function */
42 static int gost_cipher_cleanup(EVP_CIPHER_CTX *);
43 /* set/get cipher parameters */
44 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
45 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
46 /* Control function */
47 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
48
49 EVP_CIPHER cipher_gost = {
50     NID_id_Gost28147_89,
51     1,                          /* block_size */
52     32,                         /* key_size */
53     8,                          /* iv_len */
54     EVP_CIPH_CFB_MODE | EVP_CIPH_NO_PADDING |
55         EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
56     gost_cipher_init,
57     gost_cipher_do_cfb,
58     gost_cipher_cleanup,
59     sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
60     gost89_set_asn1_parameters,
61     gost89_get_asn1_parameters,
62     gost_cipher_ctl,
63     NULL,
64 };
65
66 EVP_CIPHER cipher_gost_cbc = {
67     NID_gost89_cbc,
68     8,                          /*block_size */
69     32,                         /*key_size */
70     8,                          /*iv_len */
71     EVP_CIPH_CBC_MODE |
72         EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
73     gost_cipher_init_cbc,
74     gost_cipher_do_cbc,
75     gost_cipher_cleanup,
76     sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
77     gost89_set_asn1_parameters,
78     gost89_get_asn1_parameters,
79     gost_cipher_ctl,
80     NULL,
81 };
82
83 EVP_CIPHER cipher_gost_cpacnt = {
84     NID_gost89_cnt,
85     1,                          /* block_size */
86     32,                         /* key_size */
87     8,                          /* iv_len */
88     EVP_CIPH_OFB_MODE | EVP_CIPH_NO_PADDING |
89         EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
90     gost_cipher_init_cpa,
91     gost_cipher_do_cnt,
92     gost_cipher_cleanup,
93     sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
94     gost89_set_asn1_parameters,
95     gost89_get_asn1_parameters,
96     gost_cipher_ctl,
97     NULL,
98 };
99
100 EVP_CIPHER cipher_gost_cpcnt_12 = {
101     NID_gost89_cnt_12,
102     1,                          /* block_size */
103     32,                         /* key_size */
104     8,                          /* iv_len */
105     EVP_CIPH_OFB_MODE | EVP_CIPH_NO_PADDING |
106         EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
107     gost_cipher_init_cp_12,
108     gost_cipher_do_cnt,
109     gost_cipher_cleanup,
110     sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
111     gost89_set_asn1_parameters,
112     gost89_get_asn1_parameters,
113     gost_cipher_ctl,
114     NULL,
115 };
116
117 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
118 /* Init functions which set specific parameters */
119 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
120 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx);
121 /* process block of data */
122 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
123 /* Return computed value */
124 static int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md);
125 /* Copies context */
126 static int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
127 static int gost_imit_cleanup(EVP_MD_CTX *ctx);
128 /* Control function, knows how to set MAC key.*/
129 static int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr);
130
131 EVP_MD imit_gost_cpa = {
132     NID_id_Gost28147_89_MAC,
133     NID_undef,
134     4,
135     0,
136     gost_imit_init_cpa,
137     gost_imit_update,
138     gost_imit_final,
139     gost_imit_copy,
140     gost_imit_cleanup,
141     NULL,
142     NULL,
143     {0, 0, 0, 0, 0},
144     8,
145     sizeof(struct ossl_gost_imit_ctx),
146     gost_imit_ctrl
147 };
148
149 EVP_MD imit_gost_cp_12 = {
150     NID_gost_mac_12,
151     NID_undef,
152     4,
153     0,
154     gost_imit_init_cp_12,
155     gost_imit_update,
156     gost_imit_final,
157     gost_imit_copy,
158     gost_imit_cleanup,
159     NULL,
160     NULL,
161     {0, 0, 0, 0, 0},
162     8,
163     sizeof(struct ossl_gost_imit_ctx),
164     gost_imit_ctrl
165 };
166
167 /*
168  * Correspondence between gost parameter OIDs and substitution blocks
169  * NID field is filed by register_gost_NID function in engine.c
170  * upon engine initialization
171  */
172
173 struct gost_cipher_info gost_cipher_list[] = {
174     /*- NID *//*
175      * Subst block
176      *//*
177      * Key meshing
178      */
179     /*
180      * {NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},
181      */
182     {NID_id_Gost28147_89_CryptoPro_A_ParamSet, &Gost28147_CryptoProParamSetA,
183      1},
184     {NID_id_Gost28147_89_CryptoPro_B_ParamSet, &Gost28147_CryptoProParamSetB,
185      1},
186     {NID_id_Gost28147_89_CryptoPro_C_ParamSet, &Gost28147_CryptoProParamSetC,
187      1},
188     {NID_id_Gost28147_89_CryptoPro_D_ParamSet, &Gost28147_CryptoProParamSetD,
189      1},
190     {NID_id_tc26_gost_28147_param_Z, &Gost28147_TC26ParamSetZ, 1},
191     {NID_id_Gost28147_89_TestParamSet, &Gost28147_TestParamSet, 1},
192     {NID_undef, NULL, 0}
193 };
194
195 /*
196  * get encryption parameters from crypto network settings FIXME For now we
197  * use environment var CRYPT_PARAMS as place to store these settings.
198  * Actually, it is better to use engine control command, read from
199  * configuration file to set them
200  */
201 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj)
202 {
203     int nid;
204     struct gost_cipher_info *param;
205     if (!obj) {
206         const char *params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
207         if (!params || !strlen(params)) {
208             int i;
209             for (i = 0; gost_cipher_list[i].nid != NID_undef; i++)
210                 if (gost_cipher_list[i].nid == NID_id_tc26_gost_28147_param_Z)
211                     return &gost_cipher_list[i];
212             return &gost_cipher_list[0];
213         }
214
215         nid = OBJ_txt2nid(params);
216         if (nid == NID_undef) {
217             GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
218                     GOST_R_INVALID_CIPHER_PARAM_OID);
219             return NULL;
220         }
221     } else {
222         nid = OBJ_obj2nid(obj);
223     }
224     for (param = gost_cipher_list; param->sblock != NULL && param->nid != nid;
225          param++) ;
226     if (!param->sblock) {
227         GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
228         return NULL;
229     }
230     return param;
231 }
232
233 /* Sets cipher param from paramset NID. */
234 static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid)
235 {
236     const struct gost_cipher_info *param;
237     param =
238         get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid)));
239     if (!param)
240         return 0;
241
242     c->paramNID = param->nid;
243     c->key_meshing = param->key_meshing;
244     c->count = 0;
245     gost_init(&(c->cctx), param->sblock);
246     return 1;
247 }
248
249 /* Initializes EVP_CIPHER_CTX by paramset NID */
250 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx,
251                                   const unsigned char *key,
252                                   const unsigned char *iv, int enc,
253                                   int paramNID, int mode)
254 {
255     struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
256     if (ctx->app_data == NULL) {
257         if (!gost_cipher_set_param(c, paramNID))
258             return 0;
259         ctx->app_data = ctx->cipher_data;
260     }
261     if (key)
262         gost_key(&(c->cctx), key);
263     if (iv)
264         memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
265     memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
266     return 1;
267 }
268
269 static int gost_cipher_init_cnt(EVP_CIPHER_CTX *ctx,
270                                 const unsigned char *key,
271                                 const unsigned char *iv,
272                                 gost_subst_block * block)
273 {
274     struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
275     gost_init(&(c->cctx), block);
276     c->key_meshing = 1;
277     c->count = 0;
278     if (key)
279         gost_key(&(c->cctx), key);
280     if (iv)
281         memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
282     memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
283     return 1;
284 }
285
286 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
287                                 const unsigned char *iv, int enc)
288 {
289     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_CryptoProParamSetA);
290 }
291
292 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
293                                   const unsigned char *key,
294                                   const unsigned char *iv, int enc)
295 {
296     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_TC26ParamSetZ);
297 }
298
299 /* Initializes EVP_CIPHER_CTX with default values */
300 int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
301                      const unsigned char *iv, int enc)
302 {
303     return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
304                                   EVP_CIPH_CFB_MODE);
305 }
306
307 /* Initializes EVP_CIPHER_CTX with default values */
308 int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
309                          const unsigned char *iv, int enc)
310 {
311     return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
312                                   EVP_CIPH_CBC_MODE);
313 }
314
315 /*
316  * Wrapper around gostcrypt function from gost89.c which perform key meshing
317  * when nesseccary
318  */
319 static void gost_crypt_mesh(void *ctx, unsigned char *iv, unsigned char *buf)
320 {
321     struct ossl_gost_cipher_ctx *c = ctx;
322     assert(c->count % 8 == 0 && c->count <= 1024);
323     if (c->key_meshing && c->count == 1024) {
324         cryptopro_key_meshing(&(c->cctx), iv);
325     }
326     gostcrypt(&(c->cctx), iv, buf);
327     c->count = c->count % 1024 + 8;
328 }
329
330 static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf)
331 {
332     struct ossl_gost_cipher_ctx *c = ctx;
333     word32 g, go;
334     unsigned char buf1[8];
335     assert(c->count % 8 == 0 && c->count <= 1024);
336     if (c->key_meshing && c->count == 1024) {
337         cryptopro_key_meshing(&(c->cctx), iv);
338     }
339     if (c->count == 0) {
340         gostcrypt(&(c->cctx), iv, buf1);
341     } else {
342         memcpy(buf1, iv, 8);
343     }
344     g = buf1[0] | (buf1[1] << 8) | (buf1[2] << 16) | ((word32) buf1[3] << 24);
345     g += 0x01010101;
346     buf1[0] = (unsigned char)(g & 0xff);
347     buf1[1] = (unsigned char)((g >> 8) & 0xff);
348     buf1[2] = (unsigned char)((g >> 16) & 0xff);
349     buf1[3] = (unsigned char)((g >> 24) & 0xff);
350     g = buf1[4] | (buf1[5] << 8) | (buf1[6] << 16) | ((word32) buf1[7] << 24);
351     go = g;
352     g += 0x01010104;
353     if (go > g)                 /* overflow */
354         g++;
355     buf1[4] = (unsigned char)(g & 0xff);
356     buf1[5] = (unsigned char)((g >> 8) & 0xff);
357     buf1[6] = (unsigned char)((g >> 16) & 0xff);
358     buf1[7] = (unsigned char)((g >> 24) & 0xff);
359     memcpy(iv, buf1, 8);
360     gostcrypt(&(c->cctx), buf1, buf);
361     c->count = c->count % 1024 + 8;
362 }
363
364 /* GOST encryptoon in CBC mode */
365 int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
366                        const unsigned char *in, size_t inl)
367 {
368     OPENSSL_assert(inl % 8 == 0);
369     unsigned char b[8];
370     const unsigned char *in_ptr = in;
371     unsigned char *out_ptr = out;
372     int i;
373     struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
374     if (ctx->encrypt) {
375         while (inl > 0) {
376             for (i = 0; i < 8; i++) {
377                 b[i] = ctx->iv[i] ^ in_ptr[i];
378             }
379             gostcrypt(&(c->cctx), b, out_ptr);
380             memcpy(ctx->iv, out_ptr, 8);
381             out_ptr += 8;
382             in_ptr += 8;
383             inl -= 8;
384         }
385     } else {
386         while (inl > 0) {
387             gostdecrypt(&(c->cctx), in_ptr, b);
388             for (i = 0; i < 8; i++) {
389                 out_ptr[i] = ctx->iv[i] ^ b[i];
390             }
391             memcpy(ctx->iv, in_ptr, 8);
392             out_ptr += 8;
393             in_ptr += 8;
394             inl -= 8;
395         }
396     }
397     return 1;
398 }
399
400 /* GOST encryption in CFB mode */
401 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
402                        const unsigned char *in, size_t inl)
403 {
404     const unsigned char *in_ptr = in;
405     unsigned char *out_ptr = out;
406     size_t i = 0;
407     size_t j = 0;
408 /* process partial block if any */
409     if (ctx->num) {
410         for (j = ctx->num, i = 0; j < 8 && i < inl;
411              j++, i++, in_ptr++, out_ptr++) {
412             if (!ctx->encrypt)
413                 ctx->buf[j + 8] = *in_ptr;
414             *out_ptr = ctx->buf[j] ^ (*in_ptr);
415             if (ctx->encrypt)
416                 ctx->buf[j + 8] = *out_ptr;
417         }
418         if (j == 8) {
419             memcpy(ctx->iv, ctx->buf + 8, 8);
420             ctx->num = 0;
421         } else {
422             ctx->num = j;
423             return 1;
424         }
425     }
426
427     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
428         /*
429          * block cipher current iv
430          */
431         gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf);
432         /*
433          * xor next block of input text with it and output it
434          */
435         /*
436          * output this block
437          */
438         if (!ctx->encrypt)
439             memcpy(ctx->iv, in_ptr, 8);
440         for (j = 0; j < 8; j++) {
441             out_ptr[j] = ctx->buf[j] ^ in_ptr[j];
442         }
443         /* Encrypt */
444         /* Next iv is next block of cipher text */
445         if (ctx->encrypt)
446             memcpy(ctx->iv, out_ptr, 8);
447     }
448 /* Process rest of buffer */
449     if (i < inl) {
450         gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf);
451         if (!ctx->encrypt)
452             memcpy(ctx->buf + 8, in_ptr, inl - i);
453         for (j = 0; i < inl; j++, i++) {
454             out_ptr[j] = ctx->buf[j] ^ in_ptr[j];
455         }
456         ctx->num = j;
457         if (ctx->encrypt)
458             memcpy(ctx->buf + 8, out_ptr, j);
459     } else {
460         ctx->num = 0;
461     }
462     return 1;
463 }
464
465 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
466                               const unsigned char *in, size_t inl)
467 {
468     const unsigned char *in_ptr = in;
469     unsigned char *out_ptr = out;
470     size_t i = 0;
471     size_t j;
472 /* process partial block if any */
473     if (ctx->num) {
474         for (j = ctx->num, i = 0; j < 8 && i < inl;
475              j++, i++, in_ptr++, out_ptr++) {
476             *out_ptr = ctx->buf[j] ^ (*in_ptr);
477         }
478         if (j == 8) {
479             ctx->num = 0;
480         } else {
481             ctx->num = j;
482             return 1;
483         }
484     }
485
486     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
487         /*
488          * block cipher current iv
489          */
490         /* Encrypt */
491         gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf);
492         /*
493          * xor next block of input text with it and output it
494          */
495         /*
496          * output this block
497          */
498         for (j = 0; j < 8; j++) {
499             out_ptr[j] = ctx->buf[j] ^ in_ptr[j];
500         }
501     }
502 /* Process rest of buffer */
503     if (i < inl) {
504         gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf);
505         for (j = 0; i < inl; j++, i++) {
506             out_ptr[j] = ctx->buf[j] ^ in_ptr[j];
507         }
508         ctx->num = j;
509     } else {
510         ctx->num = 0;
511     }
512     return 1;
513 }
514
515 /* Cleaning up of EVP_CIPHER_CTX */
516 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
517 {
518     gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx);
519     ctx->app_data = NULL;
520     return 1;
521 }
522
523 /* Control function for gost cipher */
524 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
525 {
526     switch (type) {
527     case EVP_CTRL_INIT:
528         {
529             struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
530             if (c == NULL) {
531                 return -1;
532             }
533             return gost_cipher_set_param(c, arg);
534         }
535     case EVP_CTRL_RAND_KEY:
536         {
537             if (RAND_bytes((unsigned char *)ptr, ctx->key_len) <= 0) {
538                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
539                 return -1;
540             }
541             break;
542         }
543     case EVP_CTRL_PBE_PRF_NID:
544         if (ptr) {
545             const char *params = get_gost_engine_param(GOST_PARAM_PBE_PARAMS);
546             int nid = NID_id_tc26_hmac_gost_3411_2012_512;
547
548             if (params) {
549                 if (!strcmp("md_gost12_256", params))
550                     nid = NID_id_tc26_hmac_gost_3411_2012_256;
551                 else if (!strcmp("md_gost12_512", params))
552                     nid = NID_id_tc26_hmac_gost_3411_2012_512;
553                 else if (!strcmp("md_gost94", params))
554                     nid = NID_id_HMACGostR3411_94;
555             }
556             *((int *)ptr) = nid;
557             return 1;
558         } else {
559             return 0;
560         }
561
562     default:
563         GOSTerr(GOST_F_GOST_CIPHER_CTL,
564                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
565         return -1;
566     }
567     return 1;
568 }
569
570 /* Set cipher parameters from ASN1 structure */
571 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
572 {
573     int len = 0;
574     unsigned char *buf = NULL;
575     unsigned char *p = NULL;
576     struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
577     GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
578     ASN1_OCTET_STRING *os = NULL;
579     if (!gcp) {
580         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
581         return 0;
582     }
583     if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) {
584         GOST_CIPHER_PARAMS_free(gcp);
585         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
586         return 0;
587     }
588     ASN1_OBJECT_free(gcp->enc_param_set);
589     gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
590
591     len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
592     p = buf = OPENSSL_malloc(len);
593     if (!buf) {
594         GOST_CIPHER_PARAMS_free(gcp);
595         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
596         return 0;
597     }
598     i2d_GOST_CIPHER_PARAMS(gcp, &p);
599     GOST_CIPHER_PARAMS_free(gcp);
600
601     os = ASN1_OCTET_STRING_new();
602
603     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
604         OPENSSL_free(buf);
605         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
606         return 0;
607     }
608     OPENSSL_free(buf);
609
610     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
611     return 1;
612 }
613
614 /* Store parameters into ASN1 structure */
615 int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
616 {
617     int ret = -1;
618     int len;
619     GOST_CIPHER_PARAMS *gcp = NULL;
620     unsigned char *p;
621     struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
622     int nid;
623
624     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
625         return ret;
626     }
627
628     p = params->value.sequence->data;
629
630     gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
631                                  params->value.sequence->length);
632
633     len = gcp->iv->length;
634     if (len != ctx->cipher->iv_len) {
635         GOST_CIPHER_PARAMS_free(gcp);
636         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH);
637         return -1;
638     }
639
640     nid = OBJ_obj2nid(gcp->enc_param_set);
641     if (nid == NID_undef) {
642         GOST_CIPHER_PARAMS_free(gcp);
643         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
644                 GOST_R_INVALID_CIPHER_PARAM_OID);
645         return -1;
646     }
647
648     if (!gost_cipher_set_param(c, nid)) {
649         GOST_CIPHER_PARAMS_free(gcp);
650         return -1;
651     }
652     memcpy(ctx->oiv, gcp->iv->data, len);
653
654     GOST_CIPHER_PARAMS_free(gcp);
655
656     return 1;
657 }
658
659 static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block)
660 {
661     struct ossl_gost_imit_ctx *c = ctx->md_data;
662     memset(c->buffer, 0, sizeof(c->buffer));
663     memset(c->partial_block, 0, sizeof(c->partial_block));
664     c->count = 0;
665     c->bytes_left = 0;
666     c->key_meshing = 1;
667     c->dgst_size = 4;
668     gost_init(&(c->cctx), block);
669     return 1;
670 }
671
672 static int gost_imit_init_cpa(EVP_MD_CTX *ctx)
673 {
674     return gost_imit_init(ctx, &Gost28147_CryptoProParamSetA);
675 }
676
677 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx)
678 {
679     return gost_imit_init(ctx, &Gost28147_TC26ParamSetZ);
680 }
681
682 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,
683                            const unsigned char *data)
684 {
685     unsigned char buffer[8];
686     /*
687      * We are using local buffer for iv because CryptoPro doesn't interpret
688      * internal state of MAC algorithm as iv during keymeshing (but does
689      * initialize internal state from iv in key transport
690      */
691     assert(c->count % 8 == 0 && c->count <= 1024);
692     if (c->key_meshing && c->count == 1024) {
693         cryptopro_key_meshing(&(c->cctx), buffer);
694     }
695     mac_block(&(c->cctx), c->buffer, data);
696     c->count = c->count % 1024 + 8;
697 }
698
699 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
700 {
701     struct ossl_gost_imit_ctx *c = ctx->md_data;
702     const unsigned char *p = data;
703     size_t bytes = count, i;
704     if (!(c->key_set)) {
705         GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
706         return 0;
707     }
708     if (c->bytes_left) {
709         for (i = c->bytes_left; i < 8 && bytes > 0; bytes--, i++, p++) {
710             c->partial_block[i] = *p;
711         }
712         if (i == 8) {
713             mac_block_mesh(c, c->partial_block);
714         } else {
715             c->bytes_left = i;
716             return 1;
717         }
718     }
719     while (bytes > 8) {
720         mac_block_mesh(c, p);
721         p += 8;
722         bytes -= 8;
723     }
724     if (bytes > 0) {
725         memcpy(c->partial_block, p, bytes);
726     }
727     c->bytes_left = bytes;
728     return 1;
729 }
730
731 int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
732 {
733     struct ossl_gost_imit_ctx *c = ctx->md_data;
734     if (!c->key_set) {
735         GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
736         return 0;
737     }
738     if (c->count == 0 && c->bytes_left) {
739         unsigned char buffer[8];
740         memset(buffer, 0, 8);
741         gost_imit_update(ctx, buffer, 8);
742     }
743     if (c->bytes_left) {
744         int i;
745         for (i = c->bytes_left; i < 8; i++) {
746             c->partial_block[i] = 0;
747         }
748         mac_block_mesh(c, c->partial_block);
749     }
750     get_mac(c->buffer, 8 * c->dgst_size, md);
751     return 1;
752 }
753
754 int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
755 {
756     switch (type) {
757     case EVP_MD_CTRL_KEY_LEN:
758         *((unsigned int *)(ptr)) = 32;
759         return 1;
760     case EVP_MD_CTRL_SET_KEY:
761         {
762             struct ossl_gost_imit_ctx *gost_imit_ctx = ctx->md_data;
763
764             if (ctx->digest->init(ctx) <= 0) {
765                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
766                 return 0;
767             }
768             ctx->flags |= EVP_MD_CTX_FLAG_NO_INIT;
769
770             if (arg == 0) {
771                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
772                 if (key->mac_param_nid != NID_undef) {
773                     const struct gost_cipher_info *param =
774                         get_encryption_params(OBJ_nid2obj
775                                               (key->mac_param_nid));
776                     if (param == NULL) {
777                         GOSTerr(GOST_F_GOST_IMIT_CTRL,
778                                 GOST_R_INVALID_MAC_PARAMS);
779                         return 0;
780                     }
781                     gost_init(&(gost_imit_ctx->cctx), param->sblock);
782                 }
783                 gost_key(&(gost_imit_ctx->cctx), key->key);
784                 gost_imit_ctx->key_set = 1;
785
786                 return 1;
787             } else if (arg == 32) {
788                 gost_key(&(gost_imit_ctx->cctx), ptr);
789                 gost_imit_ctx->key_set = 1;
790                 return 1;
791             }
792             GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
793             return 0;
794         }
795     case EVP_MD_CTRL_MAC_LEN:
796         {
797             struct ossl_gost_imit_ctx *c = ctx->md_data;
798             if (arg < 1 || arg > 8) {
799                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
800                 return 0;
801             }
802             c->dgst_size = arg;
803             return 1;
804         }
805
806     default:
807         return 0;
808     }
809 }
810
811 int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
812 {
813     memcpy(to->md_data, from->md_data, sizeof(struct ossl_gost_imit_ctx));
814     return 1;
815 }
816
817 /* Clean up imit ctx */
818 int gost_imit_cleanup(EVP_MD_CTX *ctx)
819 {
820     memset(ctx->md_data, 0, sizeof(struct ossl_gost_imit_ctx));
821     return 1;
822 }