]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_crypt.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_crypt.c
1 /**********************************************************************
2  *             gost_crypt.c - Initialize all ciphers                  *
3  *                                                                    *
4  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
5  *             Copyright (c) 2020 Chikunov Vitaly <vt@altlinux.org>   *
6  *         This file is distributed under the same license as OpenSSL *
7  *                                                                    *
8  *       OpenSSL interface to GOST 28147-89 cipher functions          *
9  *          Requires OpenSSL 0.9.9 for compilation                    *
10  **********************************************************************/
11 #include <string.h>
12 #include "gost89.h"
13 #include <openssl/err.h>
14 #include <openssl/rand.h>
15 #include "e_gost_err.h"
16 #include "gost_lcl.h"
17 #include "gost_gost2015.h"
18
19 #if !defined(CCGOST_DEBUG) && !defined(DEBUG)
20 # ifndef NDEBUG
21 #  define NDEBUG
22 # endif
23 #endif
24 #include <assert.h>
25
26 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
27                             const unsigned char *iv, int enc);
28 static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
29                                 const unsigned char *iv, int enc);
30 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
31                                 const unsigned char *iv, int enc);
32 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
33                                   const unsigned char *key,
34                                   const unsigned char *iv, int enc);
35 /* Handles block of data in CFB mode */
36 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
37                               const unsigned char *in, size_t inl);
38 /* Handles block of data in CBC mode */
39 static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
40                               const unsigned char *in, size_t inl);
41 /* Handles block of data in CNT mode */
42 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
43                               const unsigned char *in, size_t inl);
44 /* Cleanup function */
45 static int gost_cipher_cleanup(EVP_CIPHER_CTX *);
46 static int gost_magma_mgm_cleanup(EVP_CIPHER_CTX *c);
47 /* set/get cipher parameters */
48 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
49 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
50 /* Control function */
51 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
52
53 static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
54                              const unsigned char *iv, int enc);
55 static int magma_cipher_init_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, const unsigned char *key,
56                              const unsigned char *iv, int enc);
57 static int gost_magma_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key,
58                                  const unsigned char *iv, int enc);
59 /* Handles block of data in CBC mode */
60 static int magma_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
61                                const unsigned char *in, size_t inl);
62 static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
63                                const unsigned char *in, size_t inl);
64 static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
65                                const unsigned char *in, size_t inl);
66
67 static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *out,
68                                const unsigned char *in, size_t inl);
69 static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
70                                    const unsigned char *in, size_t len);
71 /* set/get cipher parameters */
72 static int magma_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
73 static int magma_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
74 /* Control function */
75 static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
76 static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
77 static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
78
79 /*
80  * Single level template accessor.
81  * Note: that you cannot template 0 value.
82  */
83 #define TPL(st,field) ( \
84     ((st)->field) ? ((st)->field) : TPL_VAL(st,field) \
85 )
86
87 #define TPL_VAL(st,field) ( \
88     ((st)->template ? (st)->template->field : 0) \
89 )
90
91 EVP_CIPHER *GOST_init_cipher(GOST_cipher *c)
92 {
93     if (c->cipher)
94         return c->cipher;
95
96     /* Some sanity checking. */
97     int flags = c->flags | TPL_VAL(c, flags);
98     int block_size = TPL(c, block_size);
99     switch (flags & EVP_CIPH_MODE) {
100     case EVP_CIPH_CBC_MODE:
101     case EVP_CIPH_ECB_MODE:
102     case EVP_CIPH_WRAP_MODE:
103         OPENSSL_assert(block_size != 1);
104         OPENSSL_assert(!(flags & EVP_CIPH_NO_PADDING));
105         break;
106     default:
107         OPENSSL_assert(block_size == 1);
108         OPENSSL_assert(flags & EVP_CIPH_NO_PADDING);
109     }
110
111     if (TPL(c, iv_len))
112         OPENSSL_assert(flags & EVP_CIPH_CUSTOM_IV);
113     else
114         OPENSSL_assert(!(flags & EVP_CIPH_CUSTOM_IV));
115
116     EVP_CIPHER *cipher;
117     if (!(cipher = EVP_CIPHER_meth_new(c->nid, block_size, TPL(c, key_len)))
118         || !EVP_CIPHER_meth_set_iv_length(cipher, TPL(c, iv_len))
119         || !EVP_CIPHER_meth_set_flags(cipher, flags)
120         || !EVP_CIPHER_meth_set_init(cipher, TPL(c, init))
121         || !EVP_CIPHER_meth_set_do_cipher(cipher, TPL(c, do_cipher))
122         || !EVP_CIPHER_meth_set_cleanup(cipher, TPL(c, cleanup))
123         || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, TPL(c, ctx_size))
124         || !EVP_CIPHER_meth_set_set_asn1_params(cipher, TPL(c, set_asn1_parameters))
125         || !EVP_CIPHER_meth_set_get_asn1_params(cipher, TPL(c, get_asn1_parameters))
126         || !EVP_CIPHER_meth_set_ctrl(cipher, TPL(c, ctrl))) {
127         EVP_CIPHER_meth_free(cipher);
128         cipher = NULL;
129     }
130     c->cipher = cipher;
131     return c->cipher;
132 }
133
134 void GOST_deinit_cipher(GOST_cipher *c)
135 {
136     if (c->cipher) {
137         EVP_CIPHER_meth_free(c->cipher);
138         c->cipher = NULL;
139     }
140 }
141
142 static GOST_cipher gost_template_cipher = {
143     .block_size = 8,
144     .key_len = 32,
145     .iv_len = 8,
146     .flags = EVP_CIPH_CUSTOM_IV |
147         EVP_CIPH_RAND_KEY |
148         EVP_CIPH_ALWAYS_CALL_INIT,
149     .cleanup = gost_cipher_cleanup,
150     .ctx_size = sizeof(struct ossl_gost_cipher_ctx),
151     .set_asn1_parameters = gost89_set_asn1_parameters,
152     .get_asn1_parameters = gost89_get_asn1_parameters,
153     .ctrl = gost_cipher_ctl,
154 };
155
156 GOST_cipher Gost28147_89_cipher = {
157     .nid = NID_id_Gost28147_89,
158     .template = &gost_template_cipher,
159     .block_size = 1,
160     .flags = EVP_CIPH_CFB_MODE |
161         EVP_CIPH_NO_PADDING,
162     .init = gost_cipher_init,
163     .do_cipher = gost_cipher_do_cfb,
164 };
165
166 GOST_cipher Gost28147_89_cbc_cipher = {
167     .nid = NID_gost89_cbc,
168     .template = &gost_template_cipher,
169     .flags = EVP_CIPH_CBC_MODE,
170     .init = gost_cipher_init_cbc,
171     .do_cipher = gost_cipher_do_cbc,
172 };
173
174 GOST_cipher Gost28147_89_cnt_cipher = {
175     .nid = NID_gost89_cnt,
176     .template = &gost_template_cipher,
177     .block_size = 1,
178     .flags = EVP_CIPH_OFB_MODE |
179         EVP_CIPH_NO_PADDING,
180     .init = gost_cipher_init_cpa,
181     .do_cipher = gost_cipher_do_cnt,
182 };
183
184 GOST_cipher Gost28147_89_cnt_12_cipher = {
185     .nid = NID_gost89_cnt_12,
186     .template = &gost_template_cipher,
187     .block_size = 1,
188     .flags = EVP_CIPH_OFB_MODE |
189         EVP_CIPH_NO_PADDING,
190     .init = gost_cipher_init_cp_12,
191     .do_cipher = gost_cipher_do_cnt,
192 };
193
194 static GOST_cipher magma_template_cipher = {
195     .block_size = 8,
196     .key_len = 32,
197     .flags =
198         EVP_CIPH_RAND_KEY |
199         EVP_CIPH_ALWAYS_CALL_INIT,
200     .cleanup = gost_cipher_cleanup,
201     .ctx_size = sizeof(struct ossl_gost_cipher_ctx),
202     .set_asn1_parameters = magma_set_asn1_parameters,
203     .get_asn1_parameters = magma_get_asn1_parameters,
204     .do_cipher = magma_cipher_do_ctr,
205     .ctrl = magma_cipher_ctl,
206 };
207
208 GOST_cipher magma_ctr_cipher = {
209     .nid = NID_magma_ctr,
210     .template = &magma_template_cipher,
211     .block_size = 1,
212     .iv_len = 4,
213     .flags = EVP_CIPH_CTR_MODE |
214         EVP_CIPH_CUSTOM_IV |
215         EVP_CIPH_NO_PADDING,
216     .init = magma_cipher_init,
217 };
218
219 GOST_cipher magma_ctr_acpkm_cipher = {
220     .nid = NID_magma_ctr_acpkm,
221     .template = &magma_template_cipher,
222     .block_size = 1,
223     .iv_len = 4,
224     .flags = EVP_CIPH_CTR_MODE |
225         EVP_CIPH_CUSTOM_IV |
226         EVP_CIPH_NO_PADDING,
227     .init = magma_cipher_init,
228 };
229
230 GOST_cipher magma_ctr_acpkm_omac_cipher = {
231     .nid = NID_magma_ctr_acpkm_omac,
232     .template = &magma_template_cipher,
233     .block_size = 1,
234     .iv_len = 4,
235     .flags = EVP_CIPH_CTR_MODE |
236         EVP_CIPH_CUSTOM_IV |
237         EVP_CIPH_NO_PADDING |
238         EVP_CIPH_CUSTOM_COPY |
239         EVP_CIPH_FLAG_CUSTOM_CIPHER |
240         EVP_CIPH_FLAG_CIPHER_WITH_MAC,
241     .init = magma_cipher_init_ctr_acpkm_omac,
242     .do_cipher = magma_cipher_do_ctr_acpkm_omac,
243     .ctrl = magma_cipher_ctl_acpkm_omac,
244 };
245
246 GOST_cipher magma_ecb_cipher = {
247     .nid = NID_magma_ecb,
248     .template = &magma_template_cipher,
249     .flags = EVP_CIPH_ECB_MODE,
250     .init = magma_cipher_init,
251     .do_cipher = magma_cipher_do_ecb,
252 };
253
254  GOST_cipher magma_mgm_cipher = {
255     .nid = NID_undef,
256     .template = &magma_template_cipher,
257     .block_size = 1,
258     .iv_len = 8,
259     .flags = EVP_CIPH_NO_PADDING |
260         EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
261         EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER,
262     .init = gost_magma_cipher_init_mgm,
263     .do_cipher = gost_magma_cipher_do_mgm,
264     .ctrl = gost_magma_mgm_ctrl,
265     .cleanup = gost_magma_mgm_cleanup,
266     .ctx_size = sizeof(gost_mgm_ctx)
267  };
268
269 static void magma_NID_callback (int nid)
270 {
271     magma_mgm_cipher.nid = nid;
272 }
273
274 GOST_NID_JOB magma_mgm_NID = {
275     .sn = SN_magma_mgm,
276     .ln = SN_magma_mgm,
277     .callback = magma_NID_callback,
278 };
279
280 GOST_cipher magma_cbc_cipher = {
281     .nid = NID_magma_cbc,
282     .template = &gost_template_cipher,
283     .iv_len = 8,
284     .flags = EVP_CIPH_CBC_MODE |
285         EVP_CIPH_CUSTOM_IV,
286     .init = magma_cipher_init,
287     .do_cipher = magma_cipher_do_cbc,
288 };
289
290 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
291 /* Init functions which set specific parameters */
292 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
293 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx);
294 /* process block of data */
295 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
296 /* Return computed value */
297 static int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md);
298 /* Copies context */
299 static int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
300 static int gost_imit_cleanup(EVP_MD_CTX *ctx);
301 /* Control function, knows how to set MAC key.*/
302 static int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr);
303
304 GOST_digest Gost28147_89_MAC_digest = {
305     .nid = NID_id_Gost28147_89_MAC,
306     .result_size = 4,
307     .input_blocksize = 8,
308     .app_datasize = sizeof(struct ossl_gost_imit_ctx),
309     .flags = EVP_MD_FLAG_XOF,
310     .init = gost_imit_init_cpa,
311     .update = gost_imit_update,
312     .final = gost_imit_final,
313     .copy = gost_imit_copy,
314     .cleanup = gost_imit_cleanup,
315     .ctrl = gost_imit_ctrl,
316 };
317
318 GOST_digest Gost28147_89_mac_12_digest = {
319     .nid = NID_gost_mac_12,
320     .result_size = 4,
321     .input_blocksize = 8,
322     .app_datasize = sizeof(struct ossl_gost_imit_ctx),
323     .flags = EVP_MD_FLAG_XOF,
324     .init = gost_imit_init_cp_12,
325     .update = gost_imit_update,
326     .final = gost_imit_final,
327     .copy = gost_imit_copy,
328     .cleanup = gost_imit_cleanup,
329     .ctrl = gost_imit_ctrl,
330 };
331
332 /*
333  * Correspondence between gost parameter OIDs and substitution blocks
334  * NID field is filed by register_gost_NID function in engine.c
335  * upon engine initialization
336  */
337
338 static struct gost_cipher_info gost_cipher_list[] = {
339     /*- NID *//*
340      * Subst block
341      *//*
342      * Key meshing
343      */
344     /*
345      * {NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},
346      */
347     {NID_id_Gost28147_89_CryptoPro_A_ParamSet, &Gost28147_CryptoProParamSetA,
348      1},
349     {NID_id_Gost28147_89_CryptoPro_B_ParamSet, &Gost28147_CryptoProParamSetB,
350      1},
351     {NID_id_Gost28147_89_CryptoPro_C_ParamSet, &Gost28147_CryptoProParamSetC,
352      1},
353     {NID_id_Gost28147_89_CryptoPro_D_ParamSet, &Gost28147_CryptoProParamSetD,
354      1},
355     {NID_id_tc26_gost_28147_param_Z, &Gost28147_TC26ParamSetZ, 1},
356     {NID_id_Gost28147_89_TestParamSet, &Gost28147_TestParamSet, 1},
357     {NID_undef, NULL, 0}
358 };
359
360 /*
361  * get encryption parameters from crypto network settings FIXME For now we
362  * use environment var CRYPT_PARAMS as place to store these settings.
363  * Actually, it is better to use engine control command, read from
364  * configuration file to set them
365  */
366 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj)
367 {
368     int nid;
369     struct gost_cipher_info *param;
370     if (!obj) {
371         const char *params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
372         if (!params || !strlen(params)) {
373             int i;
374             for (i = 0; gost_cipher_list[i].nid != NID_undef; i++)
375                 if (gost_cipher_list[i].nid == NID_id_tc26_gost_28147_param_Z)
376                     return &gost_cipher_list[i];
377             return &gost_cipher_list[0];
378         }
379
380         nid = OBJ_txt2nid(params);
381         if (nid == NID_undef) {
382             GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
383                     GOST_R_INVALID_CIPHER_PARAM_OID);
384             ERR_add_error_data(3, "Unsupported CRYPT_PARAMS='",
385                 params, "' specified in environment or in config");
386             return NULL;
387         }
388     } else {
389         nid = OBJ_obj2nid(obj);
390     }
391     for (param = gost_cipher_list; param->sblock != NULL && param->nid != nid;
392          param++) ;
393     if (!param->sblock) {
394         GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
395         return NULL;
396     }
397     return param;
398 }
399
400 /* Sets cipher param from paramset NID. */
401 static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid)
402 {
403     const struct gost_cipher_info *param;
404     param = get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid)));
405     if (!param)
406         return 0;
407
408     c->paramNID = param->nid;
409     c->key_meshing = param->key_meshing;
410     c->count = 0;
411     gost_init(&(c->cctx), param->sblock);
412     return 1;
413 }
414
415 /* Initializes EVP_CIPHER_CTX by paramset NID */
416 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx,
417                                   const unsigned char *key,
418                                   const unsigned char *iv, int enc,
419                                   int paramNID, int mode)
420 {
421     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
422     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
423         if (!gost_cipher_set_param(c, paramNID))
424             return 0;
425         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
426     }
427     if (key)
428         gost_key(&(c->cctx), key);
429     if (iv) {
430         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
431                EVP_CIPHER_CTX_iv_length(ctx));
432     }
433     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
434            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
435     return 1;
436 }
437
438 static int gost_cipher_init_cnt(EVP_CIPHER_CTX *ctx,
439                                 const unsigned char *key,
440                                 const unsigned char *iv,
441                                 gost_subst_block * block)
442 {
443     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
444     gost_init(&(c->cctx), block);
445     c->key_meshing = 1;
446     c->count = 0;
447     if (key)
448         gost_key(&(c->cctx), key);
449     if (iv) {
450         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
451                EVP_CIPHER_CTX_iv_length(ctx));
452     }
453     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
454            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
455     return 1;
456 }
457
458 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
459                                 const unsigned char *iv, int enc)
460 {
461     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_CryptoProParamSetA);
462 }
463
464 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
465                                   const unsigned char *key,
466                                   const unsigned char *iv, int enc)
467 {
468     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_TC26ParamSetZ);
469 }
470
471 /* Initializes EVP_CIPHER_CTX with default values */
472 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
473                      const unsigned char *iv, int enc)
474 {
475     return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
476                                   EVP_CIPH_CFB_MODE);
477 }
478
479 /* Initializes EVP_CIPHER_CTX with default values */
480 static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
481                          const unsigned char *iv, int enc)
482 {
483     return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
484                                   EVP_CIPH_CBC_MODE);
485 }
486
487 /* Initializes EVP_CIPHER_CTX with default values */
488 static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
489                       const unsigned char *iv, int enc)
490 {
491     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
492     /* FIXME this is just initializtion check */
493     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
494         if (!gost_cipher_set_param(c, NID_id_tc26_gost_28147_param_Z))
495             return 0;
496         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
497
498         if (enc) {
499             if (init_zero_kdf_seed(c->kdf_seed) == 0)
500                 return -1;
501         }
502     }
503
504     if (key) {
505         magma_key(&(c->cctx), key);
506         magma_master_key(&(c->cctx), key);
507     }
508     if (iv) {
509         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
510                EVP_CIPHER_CTX_iv_length(ctx));
511     }
512     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
513            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
514
515     if (EVP_CIPHER_CTX_nid(ctx) == NID_magma_ctr_acpkm
516      || EVP_CIPHER_CTX_nid(ctx) == NID_magma_ctr_acpkm_omac) {
517        c->key_meshing = 1024;
518     } else {
519        c->key_meshing = 0;
520     }
521
522     return 1;
523 }
524
525 /* Initializes EVP_CIPHER_CTX with default values */
526 static int magma_cipher_init_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, const unsigned char *key,
527                       const unsigned char *iv, int enc)
528 {
529         if (key) {
530     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
531                 unsigned char cipher_key[32];
532                 c->omac_ctx = EVP_MD_CTX_new();
533
534                 if (c->omac_ctx == NULL) {
535                     GOSTerr(GOST_F_MAGMA_CIPHER_INIT_CTR_ACPKM_OMAC, ERR_R_MALLOC_FAILURE);
536                                 return 0;
537                 }
538
539                 if (gost2015_acpkm_omac_init(NID_magma_mac, enc, key,
540                                  c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
541                     EVP_MD_CTX_free(c->omac_ctx);
542                                 c->omac_ctx = NULL;
543                     return 0;
544                 }
545
546                 return magma_cipher_init(ctx, cipher_key, iv, enc);
547         }
548
549         return magma_cipher_init(ctx, key, iv, enc);
550 }
551
552 void gost_magma_encrypt_wrap(unsigned char *in, unsigned char *out,
553                    struct ossl_gost_cipher_ctx *c) {
554     int i;
555     unsigned char b[8];
556     unsigned char d[8];
557     for (i = 0; i < 8; i++) {
558         b[7 - i] = in[i];
559     }
560     gostcrypt(&(c->cctx), b, d);
561     for (i = 0; i < 8; i++) {
562         out[7 - i] = d[i];
563     }
564 }
565
566 /* ----------------------------------------------------------------------------------------------- */
567 /*! Функция реализует операцию умножения двух элементов конечного поля \f$ \mathbb F_{2^{64}}\f$,
568     порожденного неприводимым многочленом
569     \f$ f(x) = x^{64} + x^4 + x^3 + x + 1 \in \mathbb F_2[x]\f$. Для умножения используется
570     простейшая реализация, основанная на приведении по модулю после каждого шага алгоритма.        */
571 /* ----------------------------------------------------------------------------------------------- */
572 static void gf64_mul (uint64_t *result, uint64_t *arg1, uint64_t *arg2)
573 {
574         int i = 0;
575         register uint64_t t, X0;
576         uint64_t Z0 = 0;
577
578 #ifdef L_ENDIAN
579         X0 = BSWAP64(*arg1);
580 #else
581         X0 = *arg1;
582 #endif
583
584 #ifdef L_ENDIAN
585         t = BSWAP64(*(arg2));
586 #else
587         t = *(arg2);
588 #endif
589
590         for (i = 0; i < 63; i++) {
591                 if (t & 0x1) {
592                         Z0 ^= X0;
593                 }
594                 t >>= 1;
595                 if (X0 & 0x8000000000000000) {
596                         X0 <<= 1;
597                         X0 ^= 0x1b;
598                 }
599                 else {
600                         X0 <<= 1;
601                 }
602         }
603
604         if (t & 0x1) {
605                 Z0 ^= X0;
606         }
607
608 #ifdef L_ENDIAN
609         *(result) = BSWAP64(Z0);
610 #else
611         *(result) = Z0;
612 #endif
613 }
614
615 static int gost_magma_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key,
616                                  const unsigned char *iv, int enc)
617 {
618     gost_mgm_ctx *mctx =
619         (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
620     int bl;
621
622     if (!iv && !key)
623         return 1;
624     if (key) {
625         bl = EVP_CIPHER_CTX_iv_length(ctx);
626         if (!gost_cipher_set_param(&mctx->ks.g_ks, NID_id_tc26_gost_28147_param_Z))
627             return 0;
628         magma_key(&(mctx->ks.g_ks.cctx), key);
629         gost_mgm128_init(&mctx->mgm, &mctx->ks,
630                          (block128_f) gost_magma_encrypt_wrap, gf64_mul, bl);
631
632         /*
633          * If we have an iv can set it directly, otherwise use saved IV.
634          */
635         if (iv == NULL && mctx->iv_set)
636             iv = mctx->iv;
637         if (iv) {
638             if (gost_mgm128_setiv(&mctx->mgm, iv, mctx->ivlen) != 1)
639                 return 0;
640             mctx->iv_set = 1;
641         }
642         mctx->key_set = 1;
643     } else {
644         /* If key set use IV, otherwise copy */
645         if (mctx->key_set) {
646             if (gost_mgm128_setiv(&mctx->mgm, iv, mctx->ivlen) != 1)
647                 return 0;
648         }
649         else
650             memcpy(mctx->iv, iv, mctx->ivlen);
651         mctx->iv_set = 1;
652     }
653     return 1;
654 }
655
656 /*
657  * Wrapper around gostcrypt function from gost89.c which perform key meshing
658  * when nesseccary
659  */
660 static void gost_crypt_mesh(void *ctx, unsigned char *iv, unsigned char *buf)
661 {
662     struct ossl_gost_cipher_ctx *c = ctx;
663     assert(c->count % 8 == 0 && c->count <= 1024);
664     if (c->key_meshing && c->count == 1024) {
665         cryptopro_key_meshing(&(c->cctx), iv);
666     }
667     gostcrypt(&(c->cctx), iv, buf);
668     c->count = c->count % 1024 + 8;
669 }
670
671 static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf)
672 {
673     struct ossl_gost_cipher_ctx *c = ctx;
674     word32 g, go;
675     unsigned char buf1[8];
676     assert(c->count % 8 == 0 && c->count <= 1024);
677     if (c->key_meshing && c->count == 1024) {
678         cryptopro_key_meshing(&(c->cctx), iv);
679     }
680     if (c->count == 0) {
681         gostcrypt(&(c->cctx), iv, buf1);
682     } else {
683         memcpy(buf1, iv, 8);
684     }
685     g = buf1[0] | (buf1[1] << 8) | (buf1[2] << 16) | ((word32) buf1[3] << 24);
686     g += 0x01010101;
687     buf1[0] = (unsigned char)(g & 0xff);
688     buf1[1] = (unsigned char)((g >> 8) & 0xff);
689     buf1[2] = (unsigned char)((g >> 16) & 0xff);
690     buf1[3] = (unsigned char)((g >> 24) & 0xff);
691     g = buf1[4] | (buf1[5] << 8) | (buf1[6] << 16) | ((word32) buf1[7] << 24);
692     go = g;
693     g += 0x01010104;
694     if (go > g)                 /* overflow */
695         g++;
696     buf1[4] = (unsigned char)(g & 0xff);
697     buf1[5] = (unsigned char)((g >> 8) & 0xff);
698     buf1[6] = (unsigned char)((g >> 16) & 0xff);
699     buf1[7] = (unsigned char)((g >> 24) & 0xff);
700     memcpy(iv, buf1, 8);
701     gostcrypt(&(c->cctx), buf1, buf);
702     c->count = c->count % 1024 + 8;
703 }
704
705 /* GOST encryption in CBC mode */
706 static int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
707                        const unsigned char *in, size_t inl)
708 {
709     unsigned char b[8];
710     const unsigned char *in_ptr = in;
711     unsigned char *out_ptr = out;
712     int i;
713     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
714     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
715     if (EVP_CIPHER_CTX_encrypting(ctx)) {
716         while (inl > 0) {
717
718             for (i = 0; i < 8; i++) {
719                 b[i] = iv[i] ^ in_ptr[i];
720             }
721             gostcrypt(&(c->cctx), b, out_ptr);
722             memcpy(iv, out_ptr, 8);
723             out_ptr += 8;
724             in_ptr += 8;
725             inl -= 8;
726         }
727     } else {
728         while (inl > 0) {
729             unsigned char tmpiv[8];
730             gostdecrypt(&(c->cctx), in_ptr, b);
731             memcpy(tmpiv, in_ptr, 8);
732             for (i = 0; i < 8; i++) {
733                 out_ptr[i] = iv[i] ^ b[i];
734             }
735             memcpy(iv, tmpiv, 8);
736             out_ptr += 8;
737             in_ptr += 8;
738             inl -= 8;
739         }
740     }
741     return 1;
742 }
743
744 /* MAGMA encryption in ECB mode */
745 static int magma_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
746                         const unsigned char *in, size_t inl)
747 {
748     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
749     if (EVP_CIPHER_CTX_encrypting(ctx)) {
750         while (inl > 0) {
751             magmacrypt(&(c->cctx), in, out);
752             out += 8;
753             in += 8;
754             inl -= 8;
755         }
756     } else {
757         while (inl > 0) {
758             magmadecrypt(&(c->cctx), in, out);
759             out += 8;
760             in += 8;
761             inl -= 8;
762         }
763     }
764     return 1;
765 }
766
767 /* MAGMA encryption in CBC mode */
768 static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
769                         const unsigned char *in, size_t inl)
770 {
771     unsigned char b[8];
772     unsigned char d[8];
773     const unsigned char *in_ptr = in;
774     unsigned char *out_ptr = out;
775     int i;
776     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
777     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
778     if (EVP_CIPHER_CTX_encrypting(ctx)) {
779         while (inl > 0) {
780
781             for (i = 0; i < 8; i++) {
782                 out_ptr[i] = iv[i] ^ in_ptr[i];
783             }
784             magmacrypt(&(c->cctx), out_ptr, out_ptr);
785             memcpy(iv, out_ptr, 8);
786             out_ptr += 8;
787             in_ptr += 8;
788             inl -= 8;
789         }
790     } else {
791         while (inl > 0) {
792             magmadecrypt(&(c->cctx), in_ptr, b);
793             memcpy(d, in_ptr, 8);
794             for (i = 0; i < 8; i++) {
795                 out_ptr[i] = iv[i] ^ b[i];
796             }
797             memcpy(iv, d, 8);
798             out_ptr += 8;
799             in_ptr += 8;
800             inl -= 8;
801         }
802     }
803     return 1;
804 }
805
806 /* increment counter (64-bit int) by 1 */
807 static void ctr64_inc(unsigned char *counter)
808 {
809     inc_counter(counter, 8);
810 }
811
812 #define MAGMA_BLOCK_SIZE 8
813 #define MAGMA_BLOCK_MASK (MAGMA_BLOCK_SIZE - 1)
814 static inline void apply_acpkm_magma(struct ossl_gost_cipher_ctx *
815                                            ctx, unsigned int *num)
816 {
817     if (!ctx->key_meshing || (*num < (unsigned int)ctx->key_meshing))
818         return;
819     acpkm_magma_key_meshing(&ctx->cctx);
820     *num &= MAGMA_BLOCK_MASK;
821 }
822
823 /* MAGMA encryption in CTR mode */
824 static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
825                                const unsigned char *in, size_t inl)
826 {
827     const unsigned char *in_ptr = in;
828     unsigned char *out_ptr = out;
829     size_t j;
830     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
831     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
832     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
833     unsigned int num = EVP_CIPHER_CTX_num(ctx);
834     size_t blocks, i, lasted = inl;
835 /* Process partial blocks */
836     while ((num & MAGMA_BLOCK_MASK) && lasted) {
837         *out_ptr++ = *in_ptr++ ^ buf[num & MAGMA_BLOCK_MASK];
838         --lasted;
839         num++;
840     }
841     blocks = lasted / MAGMA_BLOCK_SIZE;
842
843 /* Process full blocks */
844     for (i = 0; i < blocks; i++) {
845         apply_acpkm_magma(c, &num);
846         magmacrypt(&(c->cctx), iv, buf);
847         for (j = 0; j < 8; j++) {
848             out_ptr[j] = buf[j] ^ in_ptr[j];
849         }
850         ctr64_inc(iv);
851         c->count += MAGMA_BLOCK_SIZE;
852         in_ptr += MAGMA_BLOCK_SIZE;
853         out_ptr += MAGMA_BLOCK_SIZE;
854         num += MAGMA_BLOCK_SIZE;
855         lasted -= MAGMA_BLOCK_SIZE;
856     }
857
858 /* Process the rest of plaintext */
859     if (lasted > 0) {
860         apply_acpkm_magma(c, &num);
861         magmacrypt(&(c->cctx), iv, buf);
862
863         for (i = 0; i < lasted; i++)
864             out_ptr[i] = buf[i] ^ in_ptr[i];
865         ctr64_inc(iv);
866         c->count += 8;
867         num += lasted;
868     }
869     EVP_CIPHER_CTX_set_num(ctx, num);
870
871     return inl;
872 }
873
874 /* MAGMA encryption in CTR mode */
875 static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *out,
876                                const unsigned char *in, size_t inl)
877 {
878   struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
879
880         if (in == NULL && inl == 0) /* Final call */
881                 return gost2015_final_call(ctx, c->omac_ctx, MAGMA_MAC_MAX_SIZE, c->tag, magma_cipher_do_ctr);
882
883   if (in == NULL)
884       return -1;
885
886         /* As in and out can be the same pointer, process unencrypted here */
887         if (EVP_CIPHER_CTX_encrypting(ctx))
888                 EVP_DigestSignUpdate(c->omac_ctx, in, inl);
889
890   if (magma_cipher_do_ctr(ctx, out, in, inl) != inl)
891       return -1;
892
893         /* As in and out can be the same pointer, process decrypted here */
894         if (!EVP_CIPHER_CTX_encrypting(ctx))
895                 EVP_DigestSignUpdate(c->omac_ctx, out, inl);
896
897         return inl;
898 }
899
900 static int gost_magma_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
901                                    const unsigned char *in, size_t len)
902 {
903     gost_mgm_ctx *mctx =
904         (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
905     int enc = EVP_CIPHER_CTX_encrypting(ctx);
906
907     /* If not set up, return error */
908     if (!mctx->key_set) {
909         GOSTerr(GOST_F_GOST_MAGMA_CIPHER_DO_MGM,
910                 GOST_R_BAD_ORDER);
911         return -1;
912     }
913
914     if (!mctx->iv_set) {
915         GOSTerr(GOST_F_GOST_MAGMA_CIPHER_DO_MGM,
916                 GOST_R_BAD_ORDER);
917         return -1;
918     }
919     if (in) {
920         if (out == NULL) {
921             if (gost_mgm128_aad(&mctx->mgm, in, len))
922                 return -1;
923         } else if (enc) {
924             if (gost_mgm128_encrypt(&mctx->mgm, in, out, len))
925                 return -1;
926         } else {
927             if (gost_mgm128_decrypt(&mctx->mgm, in, out, len))
928                 return -1;
929         }
930         return len;
931     } else {
932         if (!enc) {
933             if (mctx->taglen < 0)
934                 return -1;
935             if (gost_mgm128_finish(&mctx->mgm,
936                                    EVP_CIPHER_CTX_buf_noconst(ctx),
937                                    mctx->taglen) != 0)
938                 return -1;
939             mctx->iv_set = 0;
940             return 0;
941         }
942         gost_mgm128_tag(&mctx->mgm, EVP_CIPHER_CTX_buf_noconst(ctx), 8);
943         mctx->taglen = 8;
944         /* Don't reuse the IV */
945         mctx->iv_set = 0;
946         return 0;
947     }
948
949 }
950
951 /* GOST encryption in CFB mode */
952 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
953                        const unsigned char *in, size_t inl)
954 {
955     const unsigned char *in_ptr = in;
956     unsigned char *out_ptr = out;
957     size_t i = 0;
958     size_t j = 0;
959     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
960     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
961 /* process partial block if any */
962     if (EVP_CIPHER_CTX_num(ctx)) {
963         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
964              j++, i++, in_ptr++, out_ptr++) {
965             if (!EVP_CIPHER_CTX_encrypting(ctx))
966                 buf[j + 8] = *in_ptr;
967             *out_ptr = buf[j] ^ (*in_ptr);
968             if (EVP_CIPHER_CTX_encrypting(ctx))
969                 buf[j + 8] = *out_ptr;
970         }
971         if (j == 8) {
972             memcpy(iv, buf + 8, 8);
973             EVP_CIPHER_CTX_set_num(ctx, 0);
974         } else {
975             EVP_CIPHER_CTX_set_num(ctx, j);
976             return 1;
977         }
978     }
979
980     for (; (inl - i) >= 8; i += 8, in_ptr += 8, out_ptr += 8) {
981         /*
982          * block cipher current iv
983          */
984         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
985         /*
986          * xor next block of input text with it and output it
987          */
988         /*
989          * output this block
990          */
991         if (!EVP_CIPHER_CTX_encrypting(ctx))
992             memcpy(iv, in_ptr, 8);
993         for (j = 0; j < 8; j++) {
994             out_ptr[j] = buf[j] ^ in_ptr[j];
995         }
996         /* Encrypt */
997         /* Next iv is next block of cipher text */
998         if (EVP_CIPHER_CTX_encrypting(ctx))
999             memcpy(iv, out_ptr, 8);
1000     }
1001 /* Process rest of buffer */
1002     if (i < inl) {
1003         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
1004         if (!EVP_CIPHER_CTX_encrypting(ctx))
1005             memcpy(buf + 8, in_ptr, inl - i);
1006         for (j = 0; i < inl; j++, i++) {
1007             out_ptr[j] = buf[j] ^ in_ptr[j];
1008         }
1009         EVP_CIPHER_CTX_set_num(ctx, j);
1010         if (EVP_CIPHER_CTX_encrypting(ctx))
1011             memcpy(buf + 8, out_ptr, j);
1012     } else {
1013         EVP_CIPHER_CTX_set_num(ctx, 0);
1014     }
1015     return 1;
1016 }
1017
1018 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
1019                               const unsigned char *in, size_t inl)
1020 {
1021     const unsigned char *in_ptr = in;
1022     unsigned char *out_ptr = out;
1023     size_t i = 0;
1024     size_t j;
1025     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1026     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1027 /* process partial block if any */
1028     if (EVP_CIPHER_CTX_num(ctx)) {
1029         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
1030              j++, i++, in_ptr++, out_ptr++) {
1031             *out_ptr = buf[j] ^ (*in_ptr);
1032         }
1033         if (j == 8) {
1034             EVP_CIPHER_CTX_set_num(ctx, 0);
1035         } else {
1036             EVP_CIPHER_CTX_set_num(ctx, j);
1037             return 1;
1038         }
1039     }
1040
1041     for (; (inl - i) >= 8; i += 8, in_ptr += 8, out_ptr += 8) {
1042         /*
1043          * block cipher current iv
1044          */
1045         /* Encrypt */
1046         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
1047         /*
1048          * xor next block of input text with it and output it
1049          */
1050         /*
1051          * output this block
1052          */
1053         for (j = 0; j < 8; j++) {
1054             out_ptr[j] = buf[j] ^ in_ptr[j];
1055         }
1056     }
1057 /* Process rest of buffer */
1058     if (i < inl) {
1059         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
1060         for (j = 0; i < inl; j++, i++) {
1061             out_ptr[j] = buf[j] ^ in_ptr[j];
1062         }
1063         EVP_CIPHER_CTX_set_num(ctx, j);
1064     } else {
1065         EVP_CIPHER_CTX_set_num(ctx, 0);
1066     }
1067     return 1;
1068 }
1069
1070 /* Cleaning up of EVP_CIPHER_CTX */
1071 static int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
1072 {
1073     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1074                 EVP_MD_CTX_free(c->omac_ctx);
1075     gost_destroy(&(c->cctx));
1076     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
1077     return 1;
1078 }
1079
1080 static int gost_magma_mgm_cleanup(EVP_CIPHER_CTX *c)
1081 {
1082     gost_mgm_ctx *mctx =
1083         (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c);
1084     if (mctx == NULL)
1085         return 0;
1086     gost_destroy(&mctx->ks.g_ks.cctx);
1087     OPENSSL_cleanse(&mctx->mgm, sizeof(mctx->mgm));
1088     EVP_CIPHER_CTX_set_app_data(c, NULL);
1089     return 1;
1090 }
1091
1092 static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
1093 {
1094     gost_mgm_ctx *mctx =
1095         (gost_mgm_ctx *)EVP_CIPHER_CTX_get_cipher_data(c);
1096     unsigned char *buf, *iv;
1097     int ivlen, enc;
1098
1099     switch (type) {
1100     case EVP_CTRL_INIT:
1101         ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(c));
1102         iv = EVP_CIPHER_CTX_iv_noconst(c);
1103         mctx->key_set = 0;
1104         mctx->iv_set = 0;
1105         mctx->ivlen = ivlen;
1106         mctx->iv = iv;
1107         mctx->taglen = -1;
1108         return 1;
1109
1110     case EVP_CTRL_GET_IVLEN:
1111         *(int *)ptr = mctx->ivlen;
1112         return 1;
1113
1114     case EVP_CTRL_AEAD_SET_IVLEN:
1115         if (arg <= 0)
1116             return 0;
1117         if ((arg > EVP_MAX_IV_LENGTH) && (arg > mctx->ivlen)) {
1118             // TODO: Allocate memory for IV or set error
1119             return 0;
1120         }
1121         mctx->ivlen = arg;
1122         return 1;
1123
1124     case EVP_CTRL_AEAD_SET_TAG:
1125         buf = EVP_CIPHER_CTX_buf_noconst(c);
1126         enc = EVP_CIPHER_CTX_encrypting(c);
1127         if (arg <= 0 || arg != 8 || enc) {
1128             GOSTerr(GOST_F_GOST_MAGMA_MGM_CTRL,
1129                     GOST_R_INVALID_TAG_LENGTH);
1130             return 0;
1131         }
1132         memcpy(buf, ptr, arg);
1133         mctx->taglen = arg;
1134         return 1;
1135
1136     case EVP_CTRL_AEAD_GET_TAG:
1137         buf = EVP_CIPHER_CTX_buf_noconst(c);
1138         enc = EVP_CIPHER_CTX_encrypting(c);
1139         if (arg <= 0 || arg > 8 || !enc || mctx->taglen < 0) {
1140             GOSTerr(GOST_F_GOST_MAGMA_MGM_CTRL,
1141                     GOST_R_INVALID_TAG_LENGTH);
1142             return 0;
1143         }
1144         memcpy(ptr, buf, arg);
1145         return 1;
1146
1147     default:
1148         return -1;
1149     }
1150 }
1151
1152 /* Control function for gost cipher */
1153 static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
1154 {
1155     switch (type) {
1156     case EVP_CTRL_RAND_KEY:
1157         {
1158             if (RAND_priv_bytes
1159                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
1160                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
1161                 return -1;
1162             }
1163             break;
1164         }
1165     case EVP_CTRL_PBE_PRF_NID:
1166         if (ptr) {
1167             const char *params = get_gost_engine_param(GOST_PARAM_PBE_PARAMS);
1168             int nid = NID_id_tc26_hmac_gost_3411_2012_512;
1169
1170             if (params) {
1171                 if (!strcmp("md_gost12_256", params))
1172                     nid = NID_id_tc26_hmac_gost_3411_2012_256;
1173                 else if (!strcmp("md_gost12_512", params))
1174                     nid = NID_id_tc26_hmac_gost_3411_2012_512;
1175                 else if (!strcmp("md_gost94", params))
1176                     nid = NID_id_HMACGostR3411_94;
1177             }
1178             *((int *)ptr) = nid;
1179             return 1;
1180         } else {
1181             return 0;
1182         }
1183
1184     case EVP_CTRL_SET_SBOX:
1185         if (ptr) {
1186             struct ossl_gost_cipher_ctx *c =
1187                 EVP_CIPHER_CTX_get_cipher_data(ctx);
1188             int nid;
1189             int cur_meshing;
1190             int ret;
1191
1192             if (c == NULL) {
1193                 return -1;
1194             }
1195
1196             if (c->count != 0) {
1197                 return -1;
1198             }
1199
1200             nid = OBJ_txt2nid(ptr);
1201             if (nid == NID_undef) {
1202                 return 0;
1203             }
1204
1205             cur_meshing = c->key_meshing;
1206             ret = gost_cipher_set_param(c, nid);
1207             c->key_meshing = cur_meshing;
1208             return ret;
1209         } else {
1210             return 0;
1211         }
1212     case EVP_CTRL_KEY_MESH:
1213         {
1214             struct ossl_gost_cipher_ctx *c =
1215                 EVP_CIPHER_CTX_get_cipher_data(ctx);
1216
1217             if (c == NULL) {
1218                 return -1;
1219             }
1220
1221             if (c->count != 0) {
1222                 return -1;
1223             }
1224
1225             c->key_meshing = arg;
1226             return 1;
1227         }
1228     default:
1229         GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
1230         return -1;
1231     }
1232     return 1;
1233 }
1234
1235 /* Decrement 8-byte sequence if needed */
1236 int decrement_sequence(unsigned char *seq, int decrement) {
1237     if (decrement < 0 || decrement > 1)
1238         return 0; 
1239     
1240     int j;
1241     if (decrement) {
1242        for (j = 7; j >= 0; j--)
1243             {
1244                 if (seq[j] != 0)
1245                 {
1246                     seq[j]--;
1247                     break;
1248                 }
1249                 else
1250                     seq[j] = 0xFF;
1251             }
1252     }
1253     return 1;
1254 }
1255
1256 /* Control function for gost cipher */
1257 static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
1258 {
1259     switch (type) {
1260     case EVP_CTRL_RAND_KEY:
1261             if (RAND_priv_bytes
1262                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
1263                 GOSTerr(GOST_F_MAGMA_CIPHER_CTL, GOST_R_RNG_ERROR);
1264                 return -1;
1265             }
1266             break;
1267     case EVP_CTRL_KEY_MESH:
1268         {
1269             struct ossl_gost_cipher_ctx *c =
1270                 EVP_CIPHER_CTX_get_cipher_data(ctx);
1271
1272             if (c == NULL) {
1273                 return -1;
1274             }
1275
1276             if (c->count != 0) {
1277                 return -1;
1278             }
1279
1280             c->key_meshing = arg;
1281             return 1;
1282         }
1283     case EVP_CTRL_TLSTREE:
1284         {
1285             unsigned char newkey[32];
1286             int mode = EVP_CIPHER_CTX_mode(ctx);
1287             struct ossl_gost_cipher_ctx *ctr_ctx = NULL;
1288             gost_ctx *c = NULL;
1289
1290             unsigned char adjusted_iv[8];
1291             unsigned char seq[8];
1292             int j, carry, decrement_arg;
1293             if (mode != EVP_CIPH_CTR_MODE)
1294                 return -1;
1295
1296             ctr_ctx = (struct ossl_gost_cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1297             c = &(ctr_ctx->cctx);
1298
1299             /*
1300              * 'arg' parameter indicates what we should do with sequence value.
1301              * 
1302              * When function called, seq is incremented after MAC calculation.
1303              * In ETM mode, we use seq 'as is' in the ctrl-function (arg = 0)
1304              * Otherwise we have to decrease it in the implementation (arg = 1).
1305              */
1306             memcpy(seq, ptr, 8);
1307             decrement_arg = arg;
1308             if(!decrement_sequence(seq, decrement_arg)) {
1309                 GOSTerr(GOST_F_MAGMA_CIPHER_CTL, GOST_R_CTRL_CALL_FAILED);
1310                 return -1;
1311             }
1312
1313             if (gost_tlstree(NID_magma_cbc, (const unsigned char *)c->master_key, newkey,
1314                              (const unsigned char *)seq) > 0) {
1315                 memset(adjusted_iv, 0, 8);
1316                 memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 4);
1317                 for (j = 3, carry = 0; j >= 0; j--)
1318                 {
1319                     int adj_byte = adjusted_iv[j] + seq[j+4] + carry;
1320                     carry = (adj_byte > 255) ? 1 : 0;
1321                     adjusted_iv[j] = adj_byte & 0xFF;
1322                 }
1323                 EVP_CIPHER_CTX_set_num(ctx, 0);
1324                 memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 8);
1325
1326                 magma_key(c, newkey);
1327                 return 1;
1328           }
1329         }
1330         return -1;
1331     default:
1332         GOSTerr(GOST_F_MAGMA_CIPHER_CTL, GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
1333         return -1;
1334     }
1335     return 1;
1336 }
1337
1338 static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
1339 {
1340         switch (type)
1341         {
1342                 case EVP_CTRL_PROCESS_UNPROTECTED:
1343                 {
1344                         struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1345                         STACK_OF(X509_ATTRIBUTE) *x = ptr;
1346       return gost2015_process_unprotected_attributes(x, arg, MAGMA_MAC_MAX_SIZE, c->tag);
1347                 }
1348     case EVP_CTRL_COPY: {
1349                         EVP_CIPHER_CTX *out = ptr;
1350       struct ossl_gost_cipher_ctx *in_cctx  = EVP_CIPHER_CTX_get_cipher_data(ctx);
1351       struct ossl_gost_cipher_ctx *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out);
1352
1353                         if (in_cctx->omac_ctx == out_cctx->omac_ctx) {
1354                                 out_cctx->omac_ctx = EVP_MD_CTX_new();
1355                                 if (out_cctx->omac_ctx == NULL) {
1356                                         GOSTerr(GOST_F_MAGMA_CIPHER_CTL_ACPKM_OMAC, ERR_R_MALLOC_FAILURE);
1357                                         return -1;
1358                                 }
1359                         }
1360                         return EVP_MD_CTX_copy(out_cctx->omac_ctx, in_cctx->omac_ctx);
1361                 }
1362                 default:
1363                         return magma_cipher_ctl(ctx, type, arg, ptr);
1364                         break;
1365         }
1366 }
1367
1368 /* Set cipher parameters from ASN1 structure */
1369 static int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
1370 {
1371     int len = 0;
1372     unsigned char *buf = NULL;
1373     unsigned char *p = NULL;
1374     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1375     GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
1376     ASN1_OCTET_STRING *os = NULL;
1377     if (!gcp) {
1378         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
1379         return 0;
1380     }
1381     if (!ASN1_OCTET_STRING_set
1382         (gcp->iv, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx))) {
1383         GOST_CIPHER_PARAMS_free(gcp);
1384         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
1385         return 0;
1386     }
1387     ASN1_OBJECT_free(gcp->enc_param_set);
1388     gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
1389
1390     len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
1391     p = buf = OPENSSL_malloc(len);
1392     if (!buf) {
1393         GOST_CIPHER_PARAMS_free(gcp);
1394         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
1395         return 0;
1396     }
1397     i2d_GOST_CIPHER_PARAMS(gcp, &p);
1398     GOST_CIPHER_PARAMS_free(gcp);
1399
1400     os = ASN1_OCTET_STRING_new();
1401
1402     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
1403         OPENSSL_free(buf);
1404         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
1405         return 0;
1406     }
1407     OPENSSL_free(buf);
1408
1409     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
1410     return 1;
1411 }
1412
1413 /* Store parameters into ASN1 structure */
1414 static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
1415 {
1416     int len;
1417     GOST_CIPHER_PARAMS *gcp = NULL;
1418     unsigned char *p;
1419     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1420     int nid;
1421
1422     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
1423         return -1;
1424     }
1425
1426     p = params->value.sequence->data;
1427
1428     gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
1429                                  params->value.sequence->length);
1430
1431     len = gcp->iv->length;
1432     if (len != EVP_CIPHER_CTX_iv_length(ctx)) {
1433         GOST_CIPHER_PARAMS_free(gcp);
1434         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH);
1435         return -1;
1436     }
1437
1438     nid = OBJ_obj2nid(gcp->enc_param_set);
1439     if (nid == NID_undef) {
1440         GOST_CIPHER_PARAMS_free(gcp);
1441         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
1442                 GOST_R_INVALID_CIPHER_PARAM_OID);
1443         return -1;
1444     }
1445
1446     if (!gost_cipher_set_param(c, nid)) {
1447         GOST_CIPHER_PARAMS_free(gcp);
1448         return -1;
1449     }
1450     /*XXX missing non-const accessor */
1451     memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), gcp->iv->data,
1452            EVP_CIPHER_CTX_iv_length(ctx));
1453
1454     GOST_CIPHER_PARAMS_free(gcp);
1455
1456     return 1;
1457 }
1458
1459 #define MAGMA_UKM_LEN 12
1460 static int magma_set_asn1_parameters (EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
1461 {
1462   struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1463         c->key_meshing = 8192;
1464
1465         return gost2015_set_asn1_params(params, EVP_CIPHER_CTX_original_iv(ctx), 4,
1466                 c->kdf_seed);
1467 }
1468
1469 static int magma_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
1470 {
1471   struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1472         unsigned char iv[16];
1473
1474         c->key_meshing = 8192;
1475
1476         if (gost2015_get_asn1_params(params, MAGMA_UKM_LEN, iv, 4, c->kdf_seed) < 0)
1477             return -1;
1478
1479         memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, sizeof(iv));
1480         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, sizeof(iv));
1481         /* Key meshing 8 kb*/
1482         c->key_meshing = 8192;
1483
1484         return 1;
1485 }
1486
1487 static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block)
1488 {
1489     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
1490     memset(c->buffer, 0, sizeof(c->buffer));
1491     memset(c->partial_block, 0, sizeof(c->partial_block));
1492     c->count = 0;
1493     c->bytes_left = 0;
1494     c->key_meshing = 1;
1495     c->dgst_size = 4;
1496     gost_init(&(c->cctx), block);
1497     return 1;
1498 }
1499
1500 static int gost_imit_init_cpa(EVP_MD_CTX *ctx)
1501 {
1502     return gost_imit_init(ctx, &Gost28147_CryptoProParamSetA);
1503 }
1504
1505 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx)
1506 {
1507     return gost_imit_init(ctx, &Gost28147_TC26ParamSetZ);
1508 }
1509
1510 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,
1511                            const unsigned char *data)
1512 {
1513     /*
1514      * We are using NULL for iv because CryptoPro doesn't interpret
1515      * internal state of MAC algorithm as iv during keymeshing (but does
1516      * initialize internal state from iv in key transport
1517      */
1518     assert(c->count % 8 == 0 && c->count <= 1024);
1519     if (c->key_meshing && c->count == 1024) {
1520         cryptopro_key_meshing(&(c->cctx), NULL);
1521     }
1522     mac_block(&(c->cctx), c->buffer, data);
1523     c->count = c->count % 1024 + 8;
1524 }
1525
1526 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
1527 {
1528     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
1529     const unsigned char *p = data;
1530     size_t bytes = count;
1531     if (!(c->key_set)) {
1532         GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
1533         return 0;
1534     }
1535     if (c->bytes_left) {
1536         size_t i;
1537         for (i = c->bytes_left; i < 8 && bytes > 0; bytes--, i++, p++) {
1538             c->partial_block[i] = *p;
1539         }
1540         if (i == 8) {
1541             mac_block_mesh(c, c->partial_block);
1542         } else {
1543             c->bytes_left = i;
1544             return 1;
1545         }
1546     }
1547     while (bytes > 8) {
1548         mac_block_mesh(c, p);
1549         p += 8;
1550         bytes -= 8;
1551     }
1552     if (bytes > 0) {
1553         memcpy(c->partial_block, p, bytes);
1554     }
1555     c->bytes_left = bytes;
1556     return 1;
1557 }
1558
1559 static int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
1560 {
1561     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
1562     if (!c->key_set) {
1563         GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
1564         return 0;
1565     }
1566     if (c->count == 0 && c->bytes_left) {
1567         unsigned char buffer[8];
1568         memset(buffer, 0, 8);
1569         gost_imit_update(ctx, buffer, 8);
1570     }
1571     if (c->bytes_left) {
1572         int i;
1573         for (i = c->bytes_left; i < 8; i++) {
1574             c->partial_block[i] = 0;
1575         }
1576         mac_block_mesh(c, c->partial_block);
1577     }
1578     get_mac(c->buffer, 8 * c->dgst_size, md);
1579     return 1;
1580 }
1581
1582 static int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
1583 {
1584     switch (type) {
1585     case EVP_MD_CTRL_KEY_LEN:
1586         *((unsigned int *)(ptr)) = 32;
1587         return 1;
1588     case EVP_MD_CTRL_SET_KEY:
1589         {
1590             struct ossl_gost_imit_ctx *gost_imit_ctx = EVP_MD_CTX_md_data(ctx);
1591
1592             if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
1593                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
1594                 return 0;
1595             }
1596             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
1597
1598             if (arg == 0) {
1599                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
1600                 if (key->mac_param_nid != NID_undef) {
1601                     const struct gost_cipher_info *param =
1602                         get_encryption_params(OBJ_nid2obj(key->mac_param_nid));
1603                     if (param == NULL) {
1604                         GOSTerr(GOST_F_GOST_IMIT_CTRL,
1605                                 GOST_R_INVALID_MAC_PARAMS);
1606                         return 0;
1607                     }
1608                     gost_init(&(gost_imit_ctx->cctx), param->sblock);
1609                 }
1610                 gost_key(&(gost_imit_ctx->cctx), key->key);
1611                 gost_imit_ctx->key_set = 1;
1612
1613                 return 1;
1614             } else if (arg == 32) {
1615                 gost_key(&(gost_imit_ctx->cctx), ptr);
1616                 gost_imit_ctx->key_set = 1;
1617                 return 1;
1618             }
1619             GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
1620             return 0;
1621         }
1622     case EVP_MD_CTRL_XOF_LEN:
1623         {
1624             struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
1625             if (arg < 1 || arg > 8) {
1626                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
1627                 return 0;
1628             }
1629             c->dgst_size = arg;
1630             return 1;
1631         }
1632
1633     default:
1634         return 0;
1635     }
1636 }
1637
1638 static int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
1639 {
1640     if (EVP_MD_CTX_md_data(to) && EVP_MD_CTX_md_data(from)) {
1641         memcpy(EVP_MD_CTX_md_data(to), EVP_MD_CTX_md_data(from),
1642                sizeof(struct ossl_gost_imit_ctx));
1643     }
1644     return 1;
1645 }
1646
1647 /* Clean up imit ctx */
1648 static int gost_imit_cleanup(EVP_MD_CTX *ctx)
1649 {
1650     memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(struct ossl_gost_imit_ctx));
1651     return 1;
1652 }
1653 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */