]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_crypt.c
merge upstream
[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     OPENSSL_assert(inl % 8 == 0);
497     if (EVP_CIPHER_CTX_encrypting(ctx)) {
498         while (inl > 0) {
499
500             for (i = 0; i < 8; i++) {
501                 b[i] = iv[i] ^ in_ptr[i];
502             }
503             gostcrypt(&(c->cctx), b, out_ptr);
504             memcpy(iv, out_ptr, 8);
505             out_ptr += 8;
506             in_ptr += 8;
507             inl -= 8;
508         }
509     } else {
510         while (inl > 0) {
511             gostdecrypt(&(c->cctx), in_ptr, b);
512             for (i = 0; i < 8; i++) {
513                 out_ptr[i] = iv[i] ^ b[i];
514             }
515             memcpy(iv, in_ptr, 8);
516             out_ptr += 8;
517             in_ptr += 8;
518             inl -= 8;
519         }
520     }
521     return 1;
522 }
523
524 /* GOST encryption in CFB mode */
525 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
526                        const unsigned char *in, size_t inl)
527 {
528     const unsigned char *in_ptr = in;
529     unsigned char *out_ptr = out;
530     size_t i = 0;
531     size_t j = 0;
532     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
533     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
534 /* process partial block if any */
535     if (EVP_CIPHER_CTX_num(ctx)) {
536         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
537              j++, i++, in_ptr++, out_ptr++) {
538             if (!EVP_CIPHER_CTX_encrypting(ctx))
539                 buf[j + 8] = *in_ptr;
540             *out_ptr = buf[j] ^ (*in_ptr);
541             if (EVP_CIPHER_CTX_encrypting(ctx))
542                 buf[j + 8] = *out_ptr;
543         }
544         if (j == 8) {
545             memcpy(iv, buf + 8, 8);
546             EVP_CIPHER_CTX_set_num(ctx, 0);
547         } else {
548             EVP_CIPHER_CTX_set_num(ctx, j);
549             return 1;
550         }
551     }
552
553     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
554         /*
555          * block cipher current iv
556          */
557         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
558         /*
559          * xor next block of input text with it and output it
560          */
561         /*
562          * output this block
563          */
564         if (!EVP_CIPHER_CTX_encrypting(ctx))
565             memcpy(iv, in_ptr, 8);
566         for (j = 0; j < 8; j++) {
567             out_ptr[j] = buf[j] ^ in_ptr[j];
568         }
569         /* Encrypt */
570         /* Next iv is next block of cipher text */
571         if (EVP_CIPHER_CTX_encrypting(ctx))
572             memcpy(iv, out_ptr, 8);
573     }
574 /* Process rest of buffer */
575     if (i < inl) {
576         gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
577         if (!EVP_CIPHER_CTX_encrypting(ctx))
578             memcpy(buf + 8, in_ptr, inl - i);
579         for (j = 0; i < inl; j++, i++) {
580             out_ptr[j] = buf[j] ^ in_ptr[j];
581         }
582         EVP_CIPHER_CTX_set_num(ctx, j);
583         if (EVP_CIPHER_CTX_encrypting(ctx))
584             memcpy(buf + 8, out_ptr, j);
585     } else {
586         EVP_CIPHER_CTX_set_num(ctx, 0);
587     }
588     return 1;
589 }
590
591 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
592                               const unsigned char *in, size_t inl)
593 {
594     const unsigned char *in_ptr = in;
595     unsigned char *out_ptr = out;
596     size_t i = 0;
597     size_t j;
598     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
599     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
600 /* process partial block if any */
601     if (EVP_CIPHER_CTX_num(ctx)) {
602         for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
603              j++, i++, in_ptr++, out_ptr++) {
604             *out_ptr = buf[j] ^ (*in_ptr);
605         }
606         if (j == 8) {
607             EVP_CIPHER_CTX_set_num(ctx, 0);
608         } else {
609             EVP_CIPHER_CTX_set_num(ctx, j);
610             return 1;
611         }
612     }
613
614     for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) {
615         /*
616          * block cipher current iv
617          */
618         /* Encrypt */
619         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
620         /*
621          * xor next block of input text with it and output it
622          */
623         /*
624          * output this block
625          */
626         for (j = 0; j < 8; j++) {
627             out_ptr[j] = buf[j] ^ in_ptr[j];
628         }
629     }
630 /* Process rest of buffer */
631     if (i < inl) {
632         gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf);
633         for (j = 0; i < inl; j++, i++) {
634             out_ptr[j] = buf[j] ^ in_ptr[j];
635         }
636         EVP_CIPHER_CTX_set_num(ctx, j);
637     } else {
638         EVP_CIPHER_CTX_set_num(ctx, 0);
639     }
640     return 1;
641 }
642
643 /* Cleaning up of EVP_CIPHER_CTX */
644 int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
645 {
646     gost_destroy(&
647                  ((struct ossl_gost_cipher_ctx *)
648                   EVP_CIPHER_CTX_get_cipher_data(ctx))->cctx);
649     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
650     return 1;
651 }
652
653 /* Control function for gost cipher */
654 int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
655 {
656     switch (type) {
657 #if 0
658     case EVP_CTRL_INIT:
659         {
660             struct ossl_gost_cipher_ctx *c =
661                 EVP_CIPHER_CTX_get_cipher_data(ctx);
662             if (c == NULL) {
663                 return -1;
664             }
665             return gost_cipher_set_param(c, arg);
666         }
667 #endif
668     case EVP_CTRL_RAND_KEY:
669         {
670             if (RAND_bytes
671                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
672                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
673                 return -1;
674             }
675             break;
676         }
677     case EVP_CTRL_PBE_PRF_NID:
678         if (ptr) {
679             const char *params = get_gost_engine_param(GOST_PARAM_PBE_PARAMS);
680             int nid = NID_id_tc26_hmac_gost_3411_2012_512;
681
682             if (params) {
683                 if (!strcmp("md_gost12_256", params))
684                     nid = NID_id_tc26_hmac_gost_3411_2012_256;
685                 else if (!strcmp("md_gost12_512", params))
686                     nid = NID_id_tc26_hmac_gost_3411_2012_512;
687                 else if (!strcmp("md_gost94", params))
688                     nid = NID_id_HMACGostR3411_94;
689             }
690             *((int *)ptr) = nid;
691             return 1;
692         } else {
693             return 0;
694         }
695
696     case EVP_CTRL_SET_SBOX:
697         if (ptr) {
698             struct ossl_gost_cipher_ctx *c =
699                 EVP_CIPHER_CTX_get_cipher_data(ctx);
700             int nid;
701             int cur_meshing;
702             int ret;
703
704             if (c == NULL) {
705                 return -1;
706             }
707
708             if (c->count != 0) {
709                 return -1;
710             }
711
712             nid = OBJ_txt2nid(ptr);
713             if (nid == NID_undef) {
714                 return 0;
715             }
716
717             cur_meshing = c->key_meshing;
718             ret = gost_cipher_set_param(c, nid);
719             c->key_meshing = cur_meshing;
720             return ret;
721         } else {
722             return 0;
723         }
724     case EVP_CTRL_KEY_MESH:
725         {
726             struct ossl_gost_cipher_ctx *c =
727                 EVP_CIPHER_CTX_get_cipher_data(ctx);
728
729             if (c == NULL) {
730                 return -1;
731             }
732
733             if (c->count != 0) {
734                 return -1;
735             }
736
737             c->key_meshing = arg;
738             return 1;
739         }
740     default:
741         GOSTerr(GOST_F_GOST_CIPHER_CTL,
742                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
743         return -1;
744     }
745     return 1;
746 }
747
748 /* Set cipher parameters from ASN1 structure */
749 int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
750 {
751     int len = 0;
752     unsigned char *buf = NULL;
753     unsigned char *p = NULL;
754     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
755     GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
756     ASN1_OCTET_STRING *os = NULL;
757     if (!gcp) {
758         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
759         return 0;
760     }
761     if (!ASN1_OCTET_STRING_set
762         (gcp->iv, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx))) {
763         GOST_CIPHER_PARAMS_free(gcp);
764         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
765         return 0;
766     }
767     ASN1_OBJECT_free(gcp->enc_param_set);
768     gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
769
770     len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
771     p = buf = OPENSSL_malloc(len);
772     if (!buf) {
773         GOST_CIPHER_PARAMS_free(gcp);
774         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
775         return 0;
776     }
777     i2d_GOST_CIPHER_PARAMS(gcp, &p);
778     GOST_CIPHER_PARAMS_free(gcp);
779
780     os = ASN1_OCTET_STRING_new();
781
782     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
783         OPENSSL_free(buf);
784         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
785         return 0;
786     }
787     OPENSSL_free(buf);
788
789     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
790     return 1;
791 }
792
793 /* Store parameters into ASN1 structure */
794 int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
795 {
796     int ret = -1;
797     int len;
798     GOST_CIPHER_PARAMS *gcp = NULL;
799     unsigned char *p;
800     struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
801     int nid;
802
803     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
804         return ret;
805     }
806
807     p = params->value.sequence->data;
808
809     gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
810                                  params->value.sequence->length);
811
812     len = gcp->iv->length;
813     if (len != EVP_CIPHER_CTX_iv_length(ctx)) {
814         GOST_CIPHER_PARAMS_free(gcp);
815         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH);
816         return -1;
817     }
818
819     nid = OBJ_obj2nid(gcp->enc_param_set);
820     if (nid == NID_undef) {
821         GOST_CIPHER_PARAMS_free(gcp);
822         GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
823                 GOST_R_INVALID_CIPHER_PARAM_OID);
824         return -1;
825     }
826
827     if (!gost_cipher_set_param(c, nid)) {
828         GOST_CIPHER_PARAMS_free(gcp);
829         return -1;
830     }
831     /*XXX missing non-const accessor */
832     memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), gcp->iv->data,
833            EVP_CIPHER_CTX_iv_length(ctx));
834
835     GOST_CIPHER_PARAMS_free(gcp);
836
837     return 1;
838 }
839
840 static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block)
841 {
842     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
843     memset(c->buffer, 0, sizeof(c->buffer));
844     memset(c->partial_block, 0, sizeof(c->partial_block));
845     c->count = 0;
846     c->bytes_left = 0;
847     c->key_meshing = 1;
848     c->dgst_size = 4;
849     gost_init(&(c->cctx), block);
850     return 1;
851 }
852
853 static int gost_imit_init_cpa(EVP_MD_CTX *ctx)
854 {
855     return gost_imit_init(ctx, &Gost28147_CryptoProParamSetA);
856 }
857
858 static int gost_imit_init_cp_12(EVP_MD_CTX *ctx)
859 {
860     return gost_imit_init(ctx, &Gost28147_TC26ParamSetZ);
861 }
862
863 static void mac_block_mesh(struct ossl_gost_imit_ctx *c,
864                            const unsigned char *data)
865 {
866     unsigned char buffer[8];
867     /*
868      * We are using local buffer for iv because CryptoPro doesn't interpret
869      * internal state of MAC algorithm as iv during keymeshing (but does
870      * initialize internal state from iv in key transport
871      */
872     assert(c->count % 8 == 0 && c->count <= 1024);
873     if (c->key_meshing && c->count == 1024) {
874         cryptopro_key_meshing(&(c->cctx), buffer);
875     }
876     mac_block(&(c->cctx), c->buffer, data);
877     c->count = c->count % 1024 + 8;
878 }
879
880 int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
881 {
882     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
883     const unsigned char *p = data;
884     size_t bytes = count, i;
885     if (!(c->key_set)) {
886         GOSTerr(GOST_F_GOST_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
887         return 0;
888     }
889     if (c->bytes_left) {
890         for (i = c->bytes_left; i < 8 && bytes > 0; bytes--, i++, p++) {
891             c->partial_block[i] = *p;
892         }
893         if (i == 8) {
894             mac_block_mesh(c, c->partial_block);
895         } else {
896             c->bytes_left = i;
897             return 1;
898         }
899     }
900     while (bytes > 8) {
901         mac_block_mesh(c, p);
902         p += 8;
903         bytes -= 8;
904     }
905     if (bytes > 0) {
906         memcpy(c->partial_block, p, bytes);
907     }
908     c->bytes_left = bytes;
909     return 1;
910 }
911
912 int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
913 {
914     struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
915     if (!c->key_set) {
916         GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
917         return 0;
918     }
919     if (c->count == 0 && c->bytes_left) {
920         unsigned char buffer[8];
921         memset(buffer, 0, 8);
922         gost_imit_update(ctx, buffer, 8);
923     }
924     if (c->bytes_left) {
925         int i;
926         for (i = c->bytes_left; i < 8; i++) {
927             c->partial_block[i] = 0;
928         }
929         mac_block_mesh(c, c->partial_block);
930     }
931     get_mac(c->buffer, 8 * c->dgst_size, md);
932     return 1;
933 }
934
935 int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
936 {
937     switch (type) {
938     case EVP_MD_CTRL_KEY_LEN:
939         *((unsigned int *)(ptr)) = 32;
940         return 1;
941     case EVP_MD_CTRL_SET_KEY:
942         {
943             struct ossl_gost_imit_ctx *gost_imit_ctx =
944                 EVP_MD_CTX_md_data(ctx);
945
946             if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
947                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
948                 return 0;
949             }
950             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
951
952             if (arg == 0) {
953                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
954                 if (key->mac_param_nid != NID_undef) {
955                     const struct gost_cipher_info *param =
956                         get_encryption_params(OBJ_nid2obj
957                                               (key->mac_param_nid));
958                     if (param == NULL) {
959                         GOSTerr(GOST_F_GOST_IMIT_CTRL,
960                                 GOST_R_INVALID_MAC_PARAMS);
961                         return 0;
962                     }
963                     gost_init(&(gost_imit_ctx->cctx), param->sblock);
964                 }
965                 gost_key(&(gost_imit_ctx->cctx), key->key);
966                 gost_imit_ctx->key_set = 1;
967
968                 return 1;
969             } else if (arg == 32) {
970                 gost_key(&(gost_imit_ctx->cctx), ptr);
971                 gost_imit_ctx->key_set = 1;
972                 return 1;
973             }
974             GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
975             return 0;
976         }
977     case EVP_MD_CTRL_MAC_LEN:
978         {
979             struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx);
980             if (arg < 1 || arg > 8) {
981                 GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
982                 return 0;
983             }
984             c->dgst_size = arg;
985             return 1;
986         }
987
988     default:
989         return 0;
990     }
991 }
992
993 int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
994 {
995     if (EVP_MD_CTX_md_data(to) && EVP_MD_CTX_md_data(from)) {
996         memcpy(EVP_MD_CTX_md_data(to), EVP_MD_CTX_md_data(from),
997                sizeof(struct ossl_gost_imit_ctx));
998     }
999     return 1;
1000 }
1001
1002 /* Clean up imit ctx */
1003 int gost_imit_cleanup(EVP_MD_CTX *ctx)
1004 {
1005     memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(struct ossl_gost_imit_ctx));
1006     return 1;
1007 }