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