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