]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_crypt.c
Start implementing MAGMA algorithm
[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 static int magma_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
50                                 const unsigned char *iv, int enc);
51 static EVP_CIPHER *_hidden_Gost28147_89_cipher = NULL;
52 const EVP_CIPHER *cipher_gost(void)
53 {
54     if (_hidden_Gost28147_89_cipher == NULL
55         && ((_hidden_Gost28147_89_cipher =
56              EVP_CIPHER_meth_new(NID_id_Gost28147_89, 1 /* block_size */ ,
57                                  32 /* key_size */ )) == NULL
58             || !EVP_CIPHER_meth_set_iv_length(_hidden_Gost28147_89_cipher, 8)
59             || !EVP_CIPHER_meth_set_flags(_hidden_Gost28147_89_cipher,
60                                           EVP_CIPH_CFB_MODE |
61                                           EVP_CIPH_NO_PADDING |
62                                           EVP_CIPH_CUSTOM_IV |
63                                           EVP_CIPH_RAND_KEY |
64                                           EVP_CIPH_ALWAYS_CALL_INIT)
65             || !EVP_CIPHER_meth_set_init(_hidden_Gost28147_89_cipher,
66                                          gost_cipher_init)
67             || !EVP_CIPHER_meth_set_do_cipher(_hidden_Gost28147_89_cipher,
68                                               gost_cipher_do_cfb)
69             || !EVP_CIPHER_meth_set_cleanup(_hidden_Gost28147_89_cipher,
70                                             gost_cipher_cleanup)
71             || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_Gost28147_89_cipher,
72                                                   sizeof(struct
73                                                          ossl_gost_cipher_ctx))
74             ||
75             !EVP_CIPHER_meth_set_set_asn1_params(_hidden_Gost28147_89_cipher,
76                                                  gost89_set_asn1_parameters)
77             ||
78             !EVP_CIPHER_meth_set_get_asn1_params(_hidden_Gost28147_89_cipher,
79                                                  gost89_get_asn1_parameters)
80             || !EVP_CIPHER_meth_set_ctrl(_hidden_Gost28147_89_cipher,
81                                          gost_cipher_ctl))) {
82         EVP_CIPHER_meth_free(_hidden_Gost28147_89_cipher);
83         _hidden_Gost28147_89_cipher = NULL;
84     }
85     return _hidden_Gost28147_89_cipher;
86 }
87
88 static EVP_CIPHER *_hidden_Gost28147_89_cbc = NULL;
89 const EVP_CIPHER *cipher_gost_cbc(void)
90 {
91     if (_hidden_Gost28147_89_cbc == NULL
92         && ((_hidden_Gost28147_89_cbc =
93              EVP_CIPHER_meth_new(NID_gost89_cbc, 8 /* block_size */ ,
94                                  32 /* key_size */ )) == NULL
95             || !EVP_CIPHER_meth_set_iv_length(_hidden_Gost28147_89_cbc, 8)
96             || !EVP_CIPHER_meth_set_flags(_hidden_Gost28147_89_cbc,
97                                           EVP_CIPH_CBC_MODE |
98                                           EVP_CIPH_CUSTOM_IV |
99                                           EVP_CIPH_RAND_KEY |
100                                           EVP_CIPH_ALWAYS_CALL_INIT)
101             || !EVP_CIPHER_meth_set_init(_hidden_Gost28147_89_cbc,
102                                          gost_cipher_init_cbc)
103             || !EVP_CIPHER_meth_set_do_cipher(_hidden_Gost28147_89_cbc,
104                                               gost_cipher_do_cbc)
105             || !EVP_CIPHER_meth_set_cleanup(_hidden_Gost28147_89_cbc,
106                                             gost_cipher_cleanup)
107             || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_Gost28147_89_cbc,
108                                                   sizeof(struct
109                                                          ossl_gost_cipher_ctx))
110             || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_Gost28147_89_cbc,
111                                                     gost89_set_asn1_parameters)
112             || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_Gost28147_89_cbc,
113                                                     gost89_get_asn1_parameters)
114             || !EVP_CIPHER_meth_set_ctrl(_hidden_Gost28147_89_cbc,
115                                          gost_cipher_ctl))) {
116         EVP_CIPHER_meth_free(_hidden_Gost28147_89_cbc);
117         _hidden_Gost28147_89_cbc = NULL;
118     }
119     return _hidden_Gost28147_89_cbc;
120 }
121
122 static EVP_CIPHER *_hidden_gost89_cnt = NULL;
123 const EVP_CIPHER *cipher_gost_cpacnt(void)
124 {
125     if (_hidden_gost89_cnt == NULL
126         && ((_hidden_gost89_cnt =
127              EVP_CIPHER_meth_new(NID_gost89_cnt, 1 /* block_size */ ,
128                                  32 /* key_size */ )) == NULL
129             || !EVP_CIPHER_meth_set_iv_length(_hidden_gost89_cnt, 8)
130             || !EVP_CIPHER_meth_set_flags(_hidden_gost89_cnt,
131                                           EVP_CIPH_OFB_MODE |
132                                           EVP_CIPH_NO_PADDING |
133                                           EVP_CIPH_CUSTOM_IV |
134                                           EVP_CIPH_RAND_KEY |
135                                           EVP_CIPH_ALWAYS_CALL_INIT)
136             || !EVP_CIPHER_meth_set_init(_hidden_gost89_cnt,
137                                          gost_cipher_init_cpa)
138             || !EVP_CIPHER_meth_set_do_cipher(_hidden_gost89_cnt,
139                                               gost_cipher_do_cnt)
140             || !EVP_CIPHER_meth_set_cleanup(_hidden_gost89_cnt,
141                                             gost_cipher_cleanup)
142             || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_gost89_cnt,
143                                                   sizeof(struct
144                                                          ossl_gost_cipher_ctx))
145             || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_gost89_cnt,
146                                                     gost89_set_asn1_parameters)
147             || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_gost89_cnt,
148                                                     gost89_get_asn1_parameters)
149             || !EVP_CIPHER_meth_set_ctrl(_hidden_gost89_cnt,
150                                          gost_cipher_ctl))) {
151         EVP_CIPHER_meth_free(_hidden_gost89_cnt);
152         _hidden_gost89_cnt = NULL;
153     }
154     return _hidden_gost89_cnt;
155 }
156
157 static EVP_CIPHER *_hidden_gost89_cnt_12 = NULL;
158 const EVP_CIPHER *cipher_gost_cpcnt_12(void)
159 {
160     if (_hidden_gost89_cnt_12 == NULL
161         && ((_hidden_gost89_cnt_12 =
162              EVP_CIPHER_meth_new(NID_gost89_cnt_12, 1 /* block_size */ ,
163                                  32 /* key_size */ )) == NULL
164             || !EVP_CIPHER_meth_set_iv_length(_hidden_gost89_cnt_12, 8)
165             || !EVP_CIPHER_meth_set_flags(_hidden_gost89_cnt_12,
166                                           EVP_CIPH_OFB_MODE |
167                                           EVP_CIPH_NO_PADDING |
168                                           EVP_CIPH_CUSTOM_IV |
169                                           EVP_CIPH_RAND_KEY |
170                                           EVP_CIPH_ALWAYS_CALL_INIT)
171             || !EVP_CIPHER_meth_set_init(_hidden_gost89_cnt_12,
172                                          gost_cipher_init_cp_12)
173             || !EVP_CIPHER_meth_set_do_cipher(_hidden_gost89_cnt_12,
174                                               gost_cipher_do_cnt)
175             || !EVP_CIPHER_meth_set_cleanup(_hidden_gost89_cnt_12,
176                                             gost_cipher_cleanup)
177             || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_gost89_cnt_12,
178                                                   sizeof(struct
179                                                          ossl_gost_cipher_ctx))
180             || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_gost89_cnt_12,
181                                                     gost89_set_asn1_parameters)
182             || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_gost89_cnt_12,
183                                                     gost89_get_asn1_parameters)
184             || !EVP_CIPHER_meth_set_ctrl(_hidden_gost89_cnt_12,
185                                          gost_cipher_ctl))) {
186         EVP_CIPHER_meth_free(_hidden_gost89_cnt_12);
187         _hidden_gost89_cnt_12 = NULL;
188     }
189     return _hidden_gost89_cnt_12;
190 }
191
192 static EVP_CIPHER *_hidden_magma_cbc = NULL;
193 const EVP_CIPHER *cipher_magma_cbc(void)
194 {
195     if (_hidden_magma_cbc == NULL
196         && ((_hidden_magma_cbc =
197              EVP_CIPHER_meth_new(NID_magma_cbc, 8 /* block_size */ ,
198                                  32 /* key_size */ )) == NULL
199             || !EVP_CIPHER_meth_set_iv_length(_hidden_magma_cbc, 8)
200             || !EVP_CIPHER_meth_set_flags(_hidden_magma_cbc,
201                                           EVP_CIPH_CBC_MODE |
202                                           EVP_CIPH_CUSTOM_IV |
203                                           EVP_CIPH_RAND_KEY |
204                                           EVP_CIPH_ALWAYS_CALL_INIT)
205             || !EVP_CIPHER_meth_set_init(_hidden_magma_cbc,
206                                          magma_cipher_init_cbc)
207             || !EVP_CIPHER_meth_set_do_cipher(_hidden_magma_cbc,
208                                               gost_cipher_do_cbc)
209             || !EVP_CIPHER_meth_set_cleanup(_hidden_magma_cbc,
210                                             gost_cipher_cleanup)
211             || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_magma_cbc,
212                                                   sizeof(struct
213                                                          ossl_gost_cipher_ctx))
214             || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_magma_cbc,
215                                                     gost89_set_asn1_parameters)
216             || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_magma_cbc,
217                                                     gost89_get_asn1_parameters)
218             || !EVP_CIPHER_meth_set_ctrl(_hidden_magma_cbc,
219                                          gost_cipher_ctl))) {
220         EVP_CIPHER_meth_free(_hidden_magma_cbc);
221         _hidden_magma_cbc = NULL;
222     }
223     return _hidden_magma_cbc;
224 }
225
226 void cipher_gost_destroy(void)
227 {
228     EVP_CIPHER_meth_free(_hidden_Gost28147_89_cipher);
229     _hidden_Gost28147_89_cipher = NULL;
230     EVP_CIPHER_meth_free(_hidden_gost89_cnt);
231     _hidden_gost89_cnt = NULL;
232     EVP_CIPHER_meth_free(_hidden_Gost28147_89_cbc);
233     _hidden_Gost28147_89_cbc = NULL;
234     EVP_CIPHER_meth_free(_hidden_gost89_cnt_12);
235     _hidden_gost89_cnt_12 = NULL;
236 }
237
238 /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
239 /* Init functions which set specific parameters */
240 static int gost_imit_init_cpa(EVP_MD_CTX *ctx);
241 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx);
242 /* process block of data */
243 static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count);
244 /* Return computed value */
245 static int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md);
246 /* Copies context */
247 static int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
248 static int gost_imit_cleanup(EVP_MD_CTX *ctx);
249 /* Control function, knows how to set MAC key.*/
250 static int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr);
251
252 static EVP_MD *_hidden_Gost28147_89_MAC_md = NULL;
253 static EVP_MD *_hidden_Gost28147_89_12_MAC_md = NULL;
254
255 EVP_MD *imit_gost_cpa(void)
256 {
257     if (_hidden_Gost28147_89_MAC_md == NULL) {
258         EVP_MD *md;
259
260         if ((md = EVP_MD_meth_new(NID_id_Gost28147_89_MAC, NID_undef)) == NULL
261             || !EVP_MD_meth_set_result_size(md, 4)
262             || !EVP_MD_meth_set_input_blocksize(md, 8)
263             || !EVP_MD_meth_set_app_datasize(md,
264                                              sizeof(struct
265                                                     ossl_gost_imit_ctx))
266             || !EVP_MD_meth_set_flags(md, 0)
267             || !EVP_MD_meth_set_init(md, gost_imit_init_cpa)
268             || !EVP_MD_meth_set_update(md, gost_imit_update)
269             || !EVP_MD_meth_set_final(md, gost_imit_final)
270             || !EVP_MD_meth_set_copy(md, gost_imit_copy)
271             || !EVP_MD_meth_set_cleanup(md, gost_imit_cleanup)
272             || !EVP_MD_meth_set_ctrl(md, gost_imit_ctrl)) {
273             EVP_MD_meth_free(md);
274             md = NULL;
275         }
276         _hidden_Gost28147_89_MAC_md = md;
277     }
278     return _hidden_Gost28147_89_MAC_md;
279 }
280
281 void imit_gost_cpa_destroy(void)
282 {
283     EVP_MD_meth_free(_hidden_Gost28147_89_MAC_md);
284     _hidden_Gost28147_89_MAC_md = NULL;
285 }
286
287 EVP_MD *imit_gost_cp_12(void)
288 {
289     if (_hidden_Gost28147_89_12_MAC_md == NULL) {
290         EVP_MD *md;
291
292         if ((md = EVP_MD_meth_new(NID_gost_mac_12, NID_undef)) == NULL
293             || !EVP_MD_meth_set_result_size(md, 4)
294             || !EVP_MD_meth_set_input_blocksize(md, 8)
295             || !EVP_MD_meth_set_app_datasize(md,
296                                              sizeof(struct
297                                                     ossl_gost_imit_ctx))
298             || !EVP_MD_meth_set_flags(md, 0)
299             || !EVP_MD_meth_set_init(md, gost_imit_init_cp_12)
300             || !EVP_MD_meth_set_update(md, gost_imit_update)
301             || !EVP_MD_meth_set_final(md, gost_imit_final)
302             || !EVP_MD_meth_set_copy(md, gost_imit_copy)
303             || !EVP_MD_meth_set_cleanup(md, gost_imit_cleanup)
304             || !EVP_MD_meth_set_ctrl(md, gost_imit_ctrl)) {
305             EVP_MD_meth_free(md);
306             md = NULL;
307         }
308         _hidden_Gost28147_89_12_MAC_md = md;
309     }
310     return _hidden_Gost28147_89_12_MAC_md;
311 }
312
313 void imit_gost_cp_12_destroy(void)
314 {
315     EVP_MD_meth_free(_hidden_Gost28147_89_12_MAC_md);
316     _hidden_Gost28147_89_12_MAC_md = NULL;
317 }
318
319 /*
320  * Correspondence between gost parameter OIDs and substitution blocks
321  * NID field is filed by register_gost_NID function in engine.c
322  * upon engine initialization
323  */
324
325 struct gost_cipher_info gost_cipher_list[] = {
326     /*- NID *//*
327      * Subst block
328      *//*
329      * Key meshing
330      */
331     /*
332      * {NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},
333      */
334     {NID_id_Gost28147_89_CryptoPro_A_ParamSet, &Gost28147_CryptoProParamSetA,
335      1},
336     {NID_id_Gost28147_89_CryptoPro_B_ParamSet, &Gost28147_CryptoProParamSetB,
337      1},
338     {NID_id_Gost28147_89_CryptoPro_C_ParamSet, &Gost28147_CryptoProParamSetC,
339      1},
340     {NID_id_Gost28147_89_CryptoPro_D_ParamSet, &Gost28147_CryptoProParamSetD,
341      1},
342     {NID_id_tc26_gost_28147_param_Z, &Gost28147_TC26ParamSetZ, 1},
343     {NID_id_Gost28147_89_TestParamSet, &Gost28147_TestParamSet, 1},
344     {NID_undef, NULL, 0}
345 };
346
347 /*
348  * get encryption parameters from crypto network settings FIXME For now we
349  * use environment var CRYPT_PARAMS as place to store these settings.
350  * Actually, it is better to use engine control command, read from
351  * configuration file to set them
352  */
353 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj)
354 {
355     int nid;
356     struct gost_cipher_info *param;
357     if (!obj) {
358         const char *params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
359         if (!params || !strlen(params)) {
360             int i;
361             for (i = 0; gost_cipher_list[i].nid != NID_undef; i++)
362                 if (gost_cipher_list[i].nid == NID_id_tc26_gost_28147_param_Z)
363                     return &gost_cipher_list[i];
364             return &gost_cipher_list[0];
365         }
366
367         nid = OBJ_txt2nid(params);
368         if (nid == NID_undef) {
369             GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
370                     GOST_R_INVALID_CIPHER_PARAM_OID);
371             return NULL;
372         }
373     } else {
374         nid = OBJ_obj2nid(obj);
375     }
376     for (param = gost_cipher_list; param->sblock != NULL && param->nid != nid;
377          param++) ;
378     if (!param->sblock) {
379         GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
380         return NULL;
381     }
382     return param;
383 }
384
385 /* Sets cipher param from paramset NID. */
386 static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid)
387 {
388     const struct gost_cipher_info *param;
389     param =
390         get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid)));
391     if (!param)
392         return 0;
393
394     c->paramNID = param->nid;
395     c->key_meshing = param->key_meshing;
396     c->count = 0;
397     gost_init(&(c->cctx), param->sblock);
398     return 1;
399 }
400
401 /* Initializes EVP_CIPHER_CTX by paramset NID */
402 static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx,
403                                   const unsigned char *key,
404                                   const unsigned char *iv, int enc,
405                                   int paramNID, int mode)
406 {
407     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
408     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
409         if (!gost_cipher_set_param(c, paramNID))
410             return 0;
411         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
412     }
413     if (key)
414         gost_key(&(c->cctx), key);
415     if (iv) {
416         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
417                EVP_CIPHER_CTX_iv_length(ctx));
418     }
419     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
420            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
421     return 1;
422 }
423
424 static int magma_cipher_init_param(EVP_CIPHER_CTX *ctx,
425                                   const unsigned char *key,
426                                   const unsigned char *iv, int enc,
427                                   int paramNID, int mode)
428 {
429     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
430     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
431         if (!gost_cipher_set_param(c, paramNID))
432             return 0;
433         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
434     }
435     if (key)
436         magma_key(&(c->cctx), key);
437     if (iv) {
438         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
439                EVP_CIPHER_CTX_iv_length(ctx));
440     }
441     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
442            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
443     return 1;
444 }
445
446 static int gost_cipher_init_cnt(EVP_CIPHER_CTX *ctx,
447                                 const unsigned char *key,
448                                 const unsigned char *iv,
449                                 gost_subst_block * block)
450 {
451     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
452     gost_init(&(c->cctx), block);
453     c->key_meshing = 1;
454     c->count = 0;
455     if (key)
456         gost_key(&(c->cctx), key);
457     if (iv) {
458         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
459                EVP_CIPHER_CTX_iv_length(ctx));
460     }
461     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
462            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
463     return 1;
464 }
465
466 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
467                                 const unsigned char *iv, int enc)
468 {
469     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_CryptoProParamSetA);
470 }
471
472 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
473                                   const unsigned char *key,
474                                   const unsigned char *iv, int enc)
475 {
476     return gost_cipher_init_cnt(ctx, key, iv, &Gost28147_TC26ParamSetZ);
477 }
478
479 /* Initializes EVP_CIPHER_CTX with default values */
480 int gost_cipher_init(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_CFB_MODE);
485 }
486
487 /* Initializes EVP_CIPHER_CTX with default values */
488 int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
489                          const unsigned char *iv, int enc)
490 {
491     return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
492                                   EVP_CIPH_CBC_MODE);
493 }
494
495 /* Initializes EVP_CIPHER_CTX with default values */
496 int magma_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
497                          const unsigned char *iv, int enc)
498 {
499     return magma_cipher_init_param(ctx, key, iv, enc, NID_undef,
500                                   EVP_CIPH_CBC_MODE);
501 }
502
503 /*
504  * Wrapper around gostcrypt function from gost89.c which perform key meshing
505  * when nesseccary
506  */
507 static void gost_crypt_mesh(void *ctx, unsigned char *iv, unsigned char *buf)
508 {
509     struct ossl_gost_cipher_ctx *c = ctx;
510     assert(c->count % 8 == 0 && c->count <= 1024);
511     if (c->key_meshing && c->count == 1024) {
512         cryptopro_key_meshing(&(c->cctx), iv);
513     }
514     gostcrypt(&(c->cctx), iv, buf);
515     c->count = c->count % 1024 + 8;
516 }
517
518 static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf)
519 {
520     struct ossl_gost_cipher_ctx *c = ctx;
521     word32 g, go;
522     unsigned char buf1[8];
523     assert(c->count % 8 == 0 && c->count <= 1024);
524     if (c->key_meshing && c->count == 1024) {
525         cryptopro_key_meshing(&(c->cctx), iv);
526     }
527     if (c->count == 0) {
528         gostcrypt(&(c->cctx), iv, buf1);
529     } else {
530         memcpy(buf1, iv, 8);
531     }
532     g = buf1[0] | (buf1[1] << 8) | (buf1[2] << 16) | ((word32) buf1[3] << 24);
533     g += 0x01010101;
534     buf1[0] = (unsigned char)(g & 0xff);
535     buf1[1] = (unsigned char)((g >> 8) & 0xff);
536     buf1[2] = (unsigned char)((g >> 16) & 0xff);
537     buf1[3] = (unsigned char)((g >> 24) & 0xff);
538     g = buf1[4] | (buf1[5] << 8) | (buf1[6] << 16) | ((word32) buf1[7] << 24);
539     go = g;
540     g += 0x01010104;
541     if (go > g)                 /* overflow */
542         g++;
543     buf1[4] = (unsigned char)(g & 0xff);
544     buf1[5] = (unsigned char)((g >> 8) & 0xff);
545     buf1[6] = (unsigned char)((g >> 16) & 0xff);
546     buf1[7] = (unsigned char)((g >> 24) & 0xff);
547     memcpy(iv, buf1, 8);
548     gostcrypt(&(c->cctx), buf1, buf);
549     c->count = c->count % 1024 + 8;
550 }
551
552 /* GOST encryptoon in CBC mode */
553 int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
554                        const unsigned char *in, size_t inl)
555 {
556     unsigned char b[8];
557     const unsigned char *in_ptr = in;
558     unsigned char *out_ptr = out;
559     int i;
560     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
561     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
562     if (EVP_CIPHER_CTX_encrypting(ctx)) {
563         while (inl > 0) {
564
565             for (i = 0; i < 8; i++) {
566                 b[i] = iv[i] ^ in_ptr[i];
567             }
568             gostcrypt(&(c->cctx), b, out_ptr);
569             memcpy(iv, out_ptr, 8);
570             out_ptr += 8;
571             in_ptr += 8;
572             inl -= 8;
573         }
574     } else {
575         while (inl > 0) {
576             gostdecrypt(&(c->cctx), in_ptr, b);
577             for (i = 0; i < 8; i++) {
578                 out_ptr[i] = iv[i] ^ b[i];
579             }
580             memcpy(iv, in_ptr, 8);
581             out_ptr += 8;
582             in_ptr += 8;
583             inl -= 8;
584         }
585     }
586     return 1;
587 }
588
589 /* GOST encryption in CFB mode */
590 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
591                        const unsigned char *in, size_t inl)
592 {
593     const unsigned char *in_ptr = in;
594     unsigned char *out_ptr = out;
595     size_t i = 0;
596     size_t j = 0;
597     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
598     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
599 /* process partial block if any */
600     if (EVP_CIPHER_CTX_num(ctx)) {
601         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
602              j++, i++, in_ptr++, out_ptr++) {
603             if (!EVP_CIPHER_CTX_encrypting(ctx))
604                 buf[j + 8] = *in_ptr;
605             *out_ptr = buf[j] ^ (*in_ptr);
606             if (EVP_CIPHER_CTX_encrypting(ctx))
607                 buf[j + 8] = *out_ptr;
608         }
609         if (j == 8) {
610             memcpy(iv, buf + 8, 8);
611             EVP_CIPHER_CTX_set_num(ctx, 0);
612         } else {
613             EVP_CIPHER_CTX_set_num(ctx, j);
614             return 1;
615         }
616     }
617
618     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
619         /*
620          * block cipher current iv
621          */
622         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
623         /*
624          * xor next block of input text with it and output it
625          */
626         /*
627          * output this block
628          */
629         if (!EVP_CIPHER_CTX_encrypting(ctx))
630             memcpy(iv, in_ptr, 8);
631         for (j = 0; j < 8; j++) {
632             out_ptr[j] = buf[j] ^ in_ptr[j];
633         }
634         /* Encrypt */
635         /* Next iv is next block of cipher text */
636         if (EVP_CIPHER_CTX_encrypting(ctx))
637             memcpy(iv, out_ptr, 8);
638     }
639 /* Process rest of buffer */
640     if (i < inl) {
641         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
642         if (!EVP_CIPHER_CTX_encrypting(ctx))
643             memcpy(buf + 8, in_ptr, inl - i);
644         for (j = 0; i < inl; j++, i++) {
645             out_ptr[j] = buf[j] ^ in_ptr[j];
646         }
647         EVP_CIPHER_CTX_set_num(ctx, j);
648         if (EVP_CIPHER_CTX_encrypting(ctx))
649             memcpy(buf + 8, out_ptr, j);
650     } else {
651         EVP_CIPHER_CTX_set_num(ctx, 0);
652     }
653     return 1;
654 }
655
656 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
657                               const unsigned char *in, size_t inl)
658 {
659     const unsigned char *in_ptr = in;
660     unsigned char *out_ptr = out;
661     size_t i = 0;
662     size_t j;
663     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
664     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
665 /* process partial block if any */
666     if (EVP_CIPHER_CTX_num(ctx)) {
667         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
668              j++, i++, in_ptr++, out_ptr++) {
669             *out_ptr = buf[j] ^ (*in_ptr);
670         }
671         if (j == 8) {
672             EVP_CIPHER_CTX_set_num(ctx, 0);
673         } else {
674             EVP_CIPHER_CTX_set_num(ctx, j);
675             return 1;
676         }
677     }
678
679     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
680         /*
681          * block cipher current iv
682          */
683         /* Encrypt */
684         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
685         /*
686          * xor next block of input text with it and output it
687          */
688         /*
689          * output this block
690          */
691         for (j = 0; j < 8; j++) {
692             out_ptr[j] = buf[j] ^ in_ptr[j];
693         }
694     }
695 /* Process rest of buffer */
696     if (i < inl) {
697         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
698         for (j = 0; i < inl; j++, i++) {
699             out_ptr[j] = buf[j] ^ in_ptr[j];
700         }
701         EVP_CIPHER_CTX_set_num(ctx, j);
702     } else {
703         EVP_CIPHER_CTX_set_num(ctx, 0);
704     }
705     return 1;
706 }
707
708 /* Cleaning up of EVP_CIPHER_CTX */
709 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
710 {
711     gost_destroy(&
712                  ((struct ossl_gost_cipher_ctx *)
713                   EVP_CIPHER_CTX_get_cipher_data(ctx))->cctx);
714     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
715     return 1;
716 }
717
718 /* Control function for gost cipher */
719 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
720 {
721     switch (type) {
722 #if 0
723     case EVP_CTRL_INIT:
724         {
725             struct ossl_gost_cipher_ctx *c =
726                 EVP_CIPHER_CTX_get_cipher_data(ctx);
727             if (c == NULL) {
728                 return -1;
729             }
730             return gost_cipher_set_param(c, arg);
731         }
732 #endif
733     case EVP_CTRL_RAND_KEY:
734         {
735             if (RAND_bytes
736                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
737                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
738                 return -1;
739             }
740             break;
741         }
742     case EVP_CTRL_PBE_PRF_NID:
743         if (ptr) {
744             const char *params = get_gost_engine_param(GOST_PARAM_PBE_PARAMS);
745             int nid = NID_id_tc26_hmac_gost_3411_2012_512;
746
747             if (params) {
748                 if (!strcmp("md_gost12_256", params))
749                     nid = NID_id_tc26_hmac_gost_3411_2012_256;
750                 else if (!strcmp("md_gost12_512", params))
751                     nid = NID_id_tc26_hmac_gost_3411_2012_512;
752                 else if (!strcmp("md_gost94", params))
753                     nid = NID_id_HMACGostR3411_94;
754             }
755             *((int *)ptr) = nid;
756             return 1;
757         } else {
758             return 0;
759         }
760
761     case EVP_CTRL_SET_SBOX:
762         if (ptr) {
763             struct ossl_gost_cipher_ctx *c =
764                 EVP_CIPHER_CTX_get_cipher_data(ctx);
765             int nid;
766             int cur_meshing;
767             int ret;
768
769             if (c == NULL) {
770                 return -1;
771             }
772
773             if (c->count != 0) {
774                 return -1;
775             }
776
777             nid = OBJ_txt2nid(ptr);
778             if (nid == NID_undef) {
779                 return 0;
780             }
781
782             cur_meshing = c->key_meshing;
783             ret = gost_cipher_set_param(c, nid);
784             c->key_meshing = cur_meshing;
785             return ret;
786         } else {
787             return 0;
788         }
789     case EVP_CTRL_KEY_MESH:
790         {
791             struct ossl_gost_cipher_ctx *c =
792                 EVP_CIPHER_CTX_get_cipher_data(ctx);
793
794             if (c == NULL) {
795                 return -1;
796             }
797
798             if (c->count != 0) {
799                 return -1;
800             }
801
802             c->key_meshing = arg;
803             return 1;
804         }
805     default:
806         GOSTerr(GOST_F_GOST_CIPHER_CTL,
807                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
808         return -1;
809     }
810     return 1;
811 }
812
813 /* Set cipher parameters from ASN1 structure */
814 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
815 {
816     int len = 0;
817     unsigned char *buf = NULL;
818     unsigned char *p = NULL;
819     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
820     GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
821     ASN1_OCTET_STRING *os = NULL;
822     if (!gcp) {
823         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
824         return 0;
825     }
826     if (!ASN1_OCTET_STRING_set
827         (gcp->iv, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx))) {
828         GOST_CIPHER_PARAMS_free(gcp);
829         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
830         return 0;
831     }
832     ASN1_OBJECT_free(gcp->enc_param_set);
833     gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
834
835     len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
836     p = buf = OPENSSL_malloc(len);
837     if (!buf) {
838         GOST_CIPHER_PARAMS_free(gcp);
839         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
840         return 0;
841     }
842     i2d_GOST_CIPHER_PARAMS(gcp, &p);
843     GOST_CIPHER_PARAMS_free(gcp);
844
845     os = ASN1_OCTET_STRING_new();
846
847     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
848         OPENSSL_free(buf);
849         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
850         return 0;
851     }
852     OPENSSL_free(buf);
853
854     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
855     return 1;
856 }
857
858 /* Store parameters into ASN1 structure */
859 int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
860 {
861     int ret = -1;
862     int len;
863     GOST_CIPHER_PARAMS *gcp = NULL;
864     unsigned char *p;
865     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
866     int nid;
867
868     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
869         return ret;
870     }
871
872     p = params->value.sequence->data;
873
874     gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
875                                  params->value.sequence->length);
876
877     len = gcp->iv->length;
878     if (len != EVP_CIPHER_CTX_iv_length(ctx)) {
879         GOST_CIPHER_PARAMS_free(gcp);
880         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH);
881         return -1;
882     }
883
884     nid = OBJ_obj2nid(gcp->enc_param_set);
885     if (nid == NID_undef) {
886         GOST_CIPHER_PARAMS_free(gcp);
887         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
888                 GOST_R_INVALID_CIPHER_PARAM_OID);
889         return -1;
890     }
891
892     if (!gost_cipher_set_param(c, nid)) {
893         GOST_CIPHER_PARAMS_free(gcp);
894         return -1;
895     }
896     /*XXX missing non-const accessor */
897     memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), gcp->iv->data,
898            EVP_CIPHER_CTX_iv_length(ctx));
899
900     GOST_CIPHER_PARAMS_free(gcp);
901
902     return 1;
903 }
904
905 static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block)
906 {
907     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
908     memset(c->buffer, 0, sizeof(c->buffer));
909     memset(c->partial_block, 0, sizeof(c->partial_block));
910     c->count = 0;
911     c->bytes_left = 0;
912     c->key_meshing = 1;
913     c->dgst_size = 4;
914     gost_init(&(c->cctx), block);
915     return 1;
916 }
917
918 static int gost_imit_init_cpa(EVP_MD_CTX *ctx)
919 {
920     return gost_imit_init(ctx, &Gost28147_CryptoProParamSetA);
921 }
922
923 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx)
924 {
925     return gost_imit_init(ctx, &Gost28147_TC26ParamSetZ);
926 }
927
928 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,
929                            const unsigned char *data)
930 {
931     unsigned char buffer[8];
932     /*
933      * We are using local buffer for iv because CryptoPro doesn't interpret
934      * internal state of MAC algorithm as iv during keymeshing (but does
935      * initialize internal state from iv in key transport
936      */
937     assert(c->count % 8 == 0 && c->count <= 1024);
938     if (c->key_meshing && c->count == 1024) {
939         cryptopro_key_meshing(&(c->cctx), buffer);
940     }
941     mac_block(&(c->cctx), c->buffer, data);
942     c->count = c->count % 1024 + 8;
943 }
944
945 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
946 {
947     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
948     const unsigned char *p = data;
949     size_t bytes = count, i;
950     if (!(c->key_set)) {
951         GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
952         return 0;
953     }
954     if (c->bytes_left) {
955         for (i = c->bytes_left; i < 8 && bytes > 0; bytes--, i++, p++) {
956             c->partial_block[i] = *p;
957         }
958         if (i == 8) {
959             mac_block_mesh(c, c->partial_block);
960         } else {
961             c->bytes_left = i;
962             return 1;
963         }
964     }
965     while (bytes > 8) {
966         mac_block_mesh(c, p);
967         p += 8;
968         bytes -= 8;
969     }
970     if (bytes > 0) {
971         memcpy(c->partial_block, p, bytes);
972     }
973     c->bytes_left = bytes;
974     return 1;
975 }
976
977 int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
978 {
979     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
980     if (!c->key_set) {
981         GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
982         return 0;
983     }
984     if (c->count == 0 && c->bytes_left) {
985         unsigned char buffer[8];
986         memset(buffer, 0, 8);
987         gost_imit_update(ctx, buffer, 8);
988     }
989     if (c->bytes_left) {
990         int i;
991         for (i = c->bytes_left; i < 8; i++) {
992             c->partial_block[i] = 0;
993         }
994         mac_block_mesh(c, c->partial_block);
995     }
996     get_mac(c->buffer, 8 * c->dgst_size, md);
997     return 1;
998 }
999
1000 int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
1001 {
1002     switch (type) {
1003     case EVP_MD_CTRL_KEY_LEN:
1004         *((unsigned int *)(ptr)) = 32;
1005         return 1;
1006     case EVP_MD_CTRL_SET_KEY:
1007         {
1008             struct ossl_gost_imit_ctx *gost_imit_ctx =
1009                 EVP_MD_CTX_md_data(ctx);
1010
1011             if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
1012                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
1013                 return 0;
1014             }
1015             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
1016
1017             if (arg == 0) {
1018                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
1019                 if (key->mac_param_nid != NID_undef) {
1020                     const struct gost_cipher_info *param =
1021                         get_encryption_params(OBJ_nid2obj
1022                                               (key->mac_param_nid));
1023                     if (param == NULL) {
1024                         GOSTerr(GOST_F_GOST_IMIT_CTRL,
1025                                 GOST_R_INVALID_MAC_PARAMS);
1026                         return 0;
1027                     }
1028                     gost_init(&(gost_imit_ctx->cctx), param->sblock);
1029                 }
1030                 gost_key(&(gost_imit_ctx->cctx), key->key);
1031                 gost_imit_ctx->key_set = 1;
1032
1033                 return 1;
1034             } else if (arg == 32) {
1035                 gost_key(&(gost_imit_ctx->cctx), ptr);
1036                 gost_imit_ctx->key_set = 1;
1037                 return 1;
1038             }
1039             GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
1040             return 0;
1041         }
1042     case EVP_MD_CTRL_MAC_LEN:
1043         {
1044             struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
1045             if (arg < 1 || arg > 8) {
1046                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
1047                 return 0;
1048             }
1049             c->dgst_size = arg;
1050             return 1;
1051         }
1052
1053     default:
1054         return 0;
1055     }
1056 }
1057
1058 int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
1059 {
1060     if (EVP_MD_CTX_md_data(to) && EVP_MD_CTX_md_data(from)) {
1061         memcpy(EVP_MD_CTX_md_data(to), EVP_MD_CTX_md_data(from),
1062                sizeof(struct ossl_gost_imit_ctx));
1063     }
1064     return 1;
1065 }
1066
1067 /* Clean up imit ctx */
1068 int gost_imit_cleanup(EVP_MD_CTX *ctx)
1069 {
1070     memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(struct ossl_gost_imit_ctx));
1071     return 1;
1072 }