]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
gost_grasshopper_cipher: Rework cipher registration
[openssl-gost/engine.git] / gost_grasshopper_cipher.c
1 /*
2  * Maxim Tishkov 2016
3  * Copyright (c) 2020 Vitaly Chikunov <vt@altlinux.org>
4  * This file is distributed under the same license as OpenSSL
5  */
6
7 #include "gost_grasshopper_cipher.h"
8 #include "gost_grasshopper_defines.h"
9 #include "gost_grasshopper_math.h"
10 #include "gost_grasshopper_core.h"
11 #include "gost_gost2015.h"
12
13 #include <openssl/evp.h>
14 #include <openssl/rand.h>
15 #include <openssl/err.h>
16 #include <string.h>
17
18 #include "gost_lcl.h"
19 #include "e_gost_err.h"
20
21 enum GRASSHOPPER_CIPHER_TYPE {
22     GRASSHOPPER_CIPHER_ECB = 0,
23     GRASSHOPPER_CIPHER_CBC,
24     GRASSHOPPER_CIPHER_OFB,
25     GRASSHOPPER_CIPHER_CFB,
26     GRASSHOPPER_CIPHER_CTR,
27     GRASSHOPPER_CIPHER_CTRACPKM,
28     GRASSHOPPER_CIPHER_CTRACPKMOMAC,
29 };
30
31 static EVP_CIPHER *gost_grasshopper_ciphers[7] = {
32     NULL, NULL, NULL, NULL, NULL, NULL, NULL
33 };
34
35 static GRASSHOPPER_INLINE void
36 gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c);
37
38 struct GRASSHOPPER_CIPHER_PARAMS {
39     int nid;
40     grasshopper_init_cipher_func init_cipher;
41     grasshopper_do_cipher_func do_cipher;
42     grasshopper_destroy_cipher_func destroy_cipher;
43     int block_size;
44     int ctx_size;
45     int iv_size;
46     bool padding;
47     int extra_flags;
48 };
49
50 static GOST_cipher grasshopper_template_cipher = {
51     .block_size = GRASSHOPPER_BLOCK_SIZE,
52     .key_len = GRASSHOPPER_KEY_SIZE,
53     .flags = EVP_CIPH_RAND_KEY |
54         EVP_CIPH_ALWAYS_CALL_INIT,
55     .do_cipher = gost_grasshopper_cipher_do,
56     .cleanup = gost_grasshopper_cipher_cleanup,
57     .ctx_size = sizeof(gost_grasshopper_cipher_ctx),
58     .set_asn1_parameters = gost_grasshopper_set_asn1_parameters,
59     .get_asn1_parameters = gost_grasshopper_get_asn1_parameters,
60     .ctrl = gost_grasshopper_cipher_ctl,
61 };
62
63 GOST_cipher grasshopper_ecb_cipher = {
64     .nid = NID_grasshopper_ecb,
65     .template = &grasshopper_template_cipher,
66     .flags = EVP_CIPH_ECB_MODE,
67     .init = gost_grasshopper_cipher_init_ecb,
68     .do_cipher = gost_grasshopper_cipher_do_ecb,
69 };
70
71 GOST_cipher grasshopper_cbc_cipher = {
72     .nid = NID_grasshopper_cbc,
73     .template = &grasshopper_template_cipher,
74     .iv_len = 16,
75     .flags = EVP_CIPH_CBC_MODE |
76         EVP_CIPH_CUSTOM_IV,
77     .init = gost_grasshopper_cipher_init_cbc,
78     .do_cipher = gost_grasshopper_cipher_do_cbc,
79 };
80
81 GOST_cipher grasshopper_ofb_cipher = {
82     .nid = NID_grasshopper_ofb,
83     .template = &grasshopper_template_cipher,
84     .block_size = 1,
85     .iv_len = 16,
86     .flags = EVP_CIPH_OFB_MODE |
87         EVP_CIPH_NO_PADDING |
88         EVP_CIPH_CUSTOM_IV,
89     .init = gost_grasshopper_cipher_init_ofb,
90     .do_cipher = gost_grasshopper_cipher_do_ofb,
91 };
92
93 GOST_cipher grasshopper_cfb_cipher = {
94     .nid = NID_grasshopper_cfb,
95     .template = &grasshopper_template_cipher,
96     .block_size = 1,
97     .iv_len = 16,
98     .flags = EVP_CIPH_CFB_MODE |
99         EVP_CIPH_NO_PADDING |
100         EVP_CIPH_CUSTOM_IV,
101     .init = gost_grasshopper_cipher_init_cfb,
102     .do_cipher = gost_grasshopper_cipher_do_cfb,
103 };
104
105 GOST_cipher grasshopper_ctr_cipher = {
106     .nid = NID_grasshopper_ctr,
107     .template = &grasshopper_template_cipher,
108     .block_size = 1,
109     .iv_len = 8,
110     .flags = EVP_CIPH_CTR_MODE |
111         EVP_CIPH_NO_PADDING |
112         EVP_CIPH_CUSTOM_IV,
113     .init = gost_grasshopper_cipher_init_ctr,
114     .do_cipher = gost_grasshopper_cipher_do_ctr,
115     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
116 };
117
118 GOST_cipher grasshopper_ctr_acpkm_cipher = {
119     .nid = NID_kuznyechik_ctr_acpkm,
120     .template = &grasshopper_template_cipher,
121     .block_size = 1,
122     .iv_len = 8,
123     .flags = EVP_CIPH_CTR_MODE |
124         EVP_CIPH_NO_PADDING |
125         EVP_CIPH_CUSTOM_IV,
126     .init = gost_grasshopper_cipher_init_ctracpkm,
127     .do_cipher = gost_grasshopper_cipher_do_ctracpkm,
128     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
129 };
130
131 GOST_cipher grasshopper_ctr_acpkm_omac_cipher = {
132     .nid = NID_kuznyechik_ctr_acpkm_omac,
133     .template = &grasshopper_template_cipher,
134     .block_size = 1,
135     .iv_len = 8,
136     .flags = EVP_CIPH_CTR_MODE |
137         EVP_CIPH_NO_PADDING |
138         EVP_CIPH_CUSTOM_IV |
139         EVP_CIPH_FLAG_CUSTOM_CIPHER |
140         EVP_CIPH_FLAG_CIPHER_WITH_MAC |
141         EVP_CIPH_CUSTOM_COPY,
142     .init = gost_grasshopper_cipher_init_ctracpkm_omac,
143     .do_cipher = gost_grasshopper_cipher_do_ctracpkm_omac,
144     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
145 };
146
147 static struct GRASSHOPPER_CIPHER_PARAMS gost_cipher_params[7] = {
148         {
149                 NID_grasshopper_ecb,
150                 gost_grasshopper_cipher_init_ecb,
151                 gost_grasshopper_cipher_do_ecb,
152                 NULL,
153                 16,
154                 sizeof(gost_grasshopper_cipher_ctx),
155                 0,
156                 true,
157                 0
158         },
159         {
160                 NID_grasshopper_cbc,
161                 gost_grasshopper_cipher_init_cbc,
162                 gost_grasshopper_cipher_do_cbc,
163                 NULL,
164                 16,
165                 sizeof(gost_grasshopper_cipher_ctx),
166                 16,
167                 true,
168                 0
169         },
170         {
171                 NID_grasshopper_ofb,
172                 gost_grasshopper_cipher_init_ofb,
173                 gost_grasshopper_cipher_do_ofb,
174                 NULL,
175                 1,
176                 sizeof(gost_grasshopper_cipher_ctx),
177                 16,
178                 false,
179                 0
180         },
181         {
182                 NID_grasshopper_cfb,
183                 gost_grasshopper_cipher_init_cfb,
184                 gost_grasshopper_cipher_do_cfb,
185                 NULL,
186                 1,
187                 sizeof(gost_grasshopper_cipher_ctx),
188                 16,
189                 false,
190                 0
191         },
192         {
193                 NID_grasshopper_ctr,
194                 gost_grasshopper_cipher_init_ctr,
195                 gost_grasshopper_cipher_do_ctr,
196                 gost_grasshopper_cipher_destroy_ctr,
197                 1,
198                 sizeof(gost_grasshopper_cipher_ctx_ctr),
199                 8,
200                 false,
201                 0
202         },
203         {
204                 NID_kuznyechik_ctr_acpkm,
205                 gost_grasshopper_cipher_init_ctracpkm,
206                 gost_grasshopper_cipher_do_ctracpkm,
207                 gost_grasshopper_cipher_destroy_ctr,
208                 1,
209                 sizeof(gost_grasshopper_cipher_ctx_ctr),
210                 8,
211                 false,
212                 0
213         },
214         {
215                 NID_kuznyechik_ctr_acpkm_omac,
216                 gost_grasshopper_cipher_init_ctracpkm_omac,
217                 gost_grasshopper_cipher_do_ctracpkm_omac,
218                 gost_grasshopper_cipher_destroy_ctr,
219                 1,
220                 sizeof(gost_grasshopper_cipher_ctx_ctr),
221                 8,
222                 false,
223                 EVP_CIPH_FLAG_CUSTOM_CIPHER|EVP_CIPH_FLAG_CIPHER_WITH_MAC|EVP_CIPH_CUSTOM_COPY
224         },
225 };
226
227 /* first 256 bit of D from draft-irtf-cfrg-re-keying-12 */
228 static const unsigned char ACPKM_D_2018[] = {
229     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /*  64 bit */
230     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 128 bit */
231     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
232     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 256 bit */
233 };
234
235 static void acpkm_next(gost_grasshopper_cipher_ctx * c)
236 {
237     unsigned char newkey[GRASSHOPPER_KEY_SIZE];
238     const int J = GRASSHOPPER_KEY_SIZE / GRASSHOPPER_BLOCK_SIZE;
239     int n;
240
241     for (n = 0; n < J; n++) {
242         const unsigned char *D_n = &ACPKM_D_2018[n * GRASSHOPPER_BLOCK_SIZE];
243
244         grasshopper_encrypt_block(&c->encrypt_round_keys,
245                                   (grasshopper_w128_t *) D_n,
246                                   (grasshopper_w128_t *) & newkey[n *
247                                                                   GRASSHOPPER_BLOCK_SIZE],
248                                   &c->buffer);
249     }
250     gost_grasshopper_cipher_key(c, newkey);
251 }
252
253 /* Set 256 bit  key into context */
254 GRASSHOPPER_INLINE void
255 gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx * c, const uint8_t *k)
256 {
257     int i;
258     for (i = 0; i < 2; i++) {
259         grasshopper_copy128(&c->key.k.k[i],
260                             (const grasshopper_w128_t *)(k + i * 16));
261     }
262
263     grasshopper_set_encrypt_key(&c->encrypt_round_keys, &c->key);
264     grasshopper_set_decrypt_key(&c->decrypt_round_keys, &c->key);
265 }
266
267 /* Set master 256-bit key to be used in TLSTREE calculation into context */
268 GRASSHOPPER_INLINE void
269 gost_grasshopper_master_key(gost_grasshopper_cipher_ctx * c, const uint8_t *k)
270 {
271     int i;
272     for (i = 0; i < 2; i++) {
273         grasshopper_copy128(&c->master_key.k.k[i],
274                             (const grasshopper_w128_t *)(k + i * 16));
275     }
276 }
277
278 /* Cleans up key from context */
279 GRASSHOPPER_INLINE void
280 gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx * c)
281 {
282     int i;
283     for (i = 0; i < 2; i++) {
284         grasshopper_zero128(&c->key.k.k[i]);
285         grasshopper_zero128(&c->master_key.k.k[i]);
286     }
287     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
288         grasshopper_zero128(&c->encrypt_round_keys.k[i]);
289     }
290     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
291         grasshopper_zero128(&c->decrypt_round_keys.k[i]);
292     }
293     grasshopper_zero128(&c->buffer);
294 }
295
296 static GRASSHOPPER_INLINE void
297 gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c)
298 {
299     gost_grasshopper_cipher_ctx_ctr *ctx =
300         (gost_grasshopper_cipher_ctx_ctr *) c;
301
302     if (ctx->omac_ctx)
303         EVP_MD_CTX_free(ctx->omac_ctx);
304
305     grasshopper_zero128(&ctx->partial_buffer);
306 }
307
308 int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx,
309                                  const unsigned char *key,
310                                  const unsigned char *iv, int enc)
311 {
312     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
313
314     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
315         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
316         if (enc && c->type == GRASSHOPPER_CIPHER_CTRACPKM) {
317             gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
318             if (init_zero_kdf_seed(ctr->kdf_seed) == 0)
319                 return -1;
320         }
321     }
322
323     if (key != NULL) {
324         gost_grasshopper_cipher_key(c, key);
325         gost_grasshopper_master_key(c, key);
326     }
327
328     if (iv != NULL) {
329         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
330                EVP_CIPHER_CTX_iv_length(ctx));
331     }
332
333     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
334            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
335
336     grasshopper_zero128(&c->buffer);
337
338     return 1;
339 }
340
341 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX *ctx, const unsigned char
342                                                         *key, const unsigned char
343                                                         *iv, int enc)
344 {
345     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
346     c->type = GRASSHOPPER_CIPHER_ECB;
347     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
348 }
349
350 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char
351                                                         *key, const unsigned char
352                                                         *iv, int enc)
353 {
354     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
355     c->type = GRASSHOPPER_CIPHER_CBC;
356     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
357 }
358
359 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX *ctx, const unsigned char
360                                                         *key, const unsigned char
361                                                         *iv, int enc)
362 {
363     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
364     c->type = GRASSHOPPER_CIPHER_OFB;
365     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
366 }
367
368 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX *ctx, const unsigned char
369                                                         *key, const unsigned char
370                                                         *iv, int enc)
371 {
372     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
373     c->type = GRASSHOPPER_CIPHER_CFB;
374     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
375 }
376
377 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx, const unsigned char
378                                                         *key, const unsigned char
379                                                         *iv, int enc)
380 {
381     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
382
383     c->c.type = GRASSHOPPER_CIPHER_CTR;
384     EVP_CIPHER_CTX_set_num(ctx, 0);
385
386     grasshopper_zero128(&c->partial_buffer);
387
388     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
389 }
390
391 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX
392                                                              *ctx, const unsigned
393                                                              char *key, const unsigned
394                                                              char *iv, int enc)
395 {
396     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
397
398     /* NB: setting type makes EVP do_cipher callback useless */
399     c->c.type = GRASSHOPPER_CIPHER_CTRACPKM;
400     EVP_CIPHER_CTX_set_num(ctx, 0);
401     c->section_size = 4096;
402
403     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
404 }
405
406 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctracpkm_omac(EVP_CIPHER_CTX
407                                                              *ctx, const unsigned
408                                                              char *key, const unsigned
409                                                              char *iv, int enc)
410 {
411         gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
412
413         /* NB: setting type makes EVP do_cipher callback useless */
414         c->c.type = GRASSHOPPER_CIPHER_CTRACPKMOMAC;
415         EVP_CIPHER_CTX_set_num(ctx, 0);
416         c->section_size = 4096;
417
418         if (key) {
419                 unsigned char cipher_key[32];
420                 c->omac_ctx = EVP_MD_CTX_new();
421
422                 if (c->omac_ctx == NULL) {
423                     GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC, ERR_R_MALLOC_FAILURE);
424                                 return 0;
425                 }
426
427                 if (gost2015_acpkm_omac_init(NID_kuznyechik_mac, enc, key,
428                                  c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
429                     EVP_MD_CTX_free(c->omac_ctx);
430                                 c->omac_ctx = NULL;
431                     return 0;
432                 }
433
434                 return gost_grasshopper_cipher_init(ctx, cipher_key, iv, enc);
435         }
436
437         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
438 }
439
440 GRASSHOPPER_INLINE int gost_grasshopper_cipher_do(EVP_CIPHER_CTX *ctx,
441                                                   unsigned char *out,
442                                                   const unsigned char *in,
443                                                   size_t inl)
444 {
445     gost_grasshopper_cipher_ctx *c =
446         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
447     struct GRASSHOPPER_CIPHER_PARAMS *params = &gost_cipher_params[c->type];
448
449     return params->do_cipher(ctx, out, in, inl);
450 }
451
452 int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
453                                    const unsigned char *in, size_t inl)
454 {
455     gost_grasshopper_cipher_ctx *c =
456         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
457     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
458     const unsigned char *current_in = in;
459     unsigned char *current_out = out;
460     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
461     size_t i;
462
463     for (i = 0; i < blocks;
464          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
465          GRASSHOPPER_BLOCK_SIZE) {
466         if (encrypting) {
467             grasshopper_encrypt_block(&c->encrypt_round_keys,
468                                       (grasshopper_w128_t *) current_in,
469                                       (grasshopper_w128_t *) current_out,
470                                       &c->buffer);
471         } else {
472             grasshopper_decrypt_block(&c->decrypt_round_keys,
473                                       (grasshopper_w128_t *) current_in,
474                                       (grasshopper_w128_t *) current_out,
475                                       &c->buffer);
476         }
477     }
478
479     return 1;
480 }
481
482 int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
483                                    const unsigned char *in, size_t inl)
484 {
485     gost_grasshopper_cipher_ctx *c =
486         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
487     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
488     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
489     const unsigned char *current_in = in;
490     unsigned char *current_out = out;
491     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
492     size_t i;
493     grasshopper_w128_t *currentBlock;
494
495     currentBlock = (grasshopper_w128_t *) iv;
496
497     for (i = 0; i < blocks;
498          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
499          GRASSHOPPER_BLOCK_SIZE) {
500         grasshopper_w128_t *currentInputBlock = (grasshopper_w128_t *) current_in;
501         grasshopper_w128_t *currentOutputBlock = (grasshopper_w128_t *) current_out;
502         if (encrypting) {
503             grasshopper_append128(currentBlock, currentInputBlock);
504             grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock,
505                                       currentOutputBlock, &c->buffer);
506             grasshopper_copy128(currentBlock, currentOutputBlock);
507         } else {
508             grasshopper_w128_t tmp;
509
510             grasshopper_copy128(&tmp, currentInputBlock);
511             grasshopper_decrypt_block(&c->decrypt_round_keys,
512                                       currentInputBlock, currentOutputBlock,
513                                       &c->buffer);
514             grasshopper_append128(currentOutputBlock, currentBlock);
515             grasshopper_copy128(currentBlock, &tmp);
516         }
517     }
518
519     return 1;
520 }
521
522 void inc_counter(unsigned char *counter, size_t counter_bytes)
523 {
524     unsigned int n = counter_bytes;
525
526     do {
527         unsigned char c;
528         --n;
529         c = counter[n];
530         ++c;
531         counter[n] = c;
532         if (c)
533             return;
534     } while (n);
535 }
536
537 /* increment counter (128-bit int) by 1 */
538 static void ctr128_inc(unsigned char *counter)
539 {
540     inc_counter(counter, 16);
541 }
542
543 int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
544                                    const unsigned char *in, size_t inl)
545 {
546     gost_grasshopper_cipher_ctx_ctr *c = (gost_grasshopper_cipher_ctx_ctr *)
547         EVP_CIPHER_CTX_get_cipher_data(ctx);
548     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
549     const unsigned char *current_in = in;
550     unsigned char *current_out = out;
551     grasshopper_w128_t *currentInputBlock;
552     grasshopper_w128_t *currentOutputBlock;
553     unsigned int n = EVP_CIPHER_CTX_num(ctx);
554     size_t lasted = inl;
555     size_t i;
556     size_t blocks;
557     grasshopper_w128_t *iv_buffer;
558     grasshopper_w128_t tmp;
559
560     while (n && lasted) {
561         *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n];
562         --lasted;
563         n = (n + 1) % GRASSHOPPER_BLOCK_SIZE;
564     }
565     EVP_CIPHER_CTX_set_num(ctx, n);
566     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
567
568     iv_buffer = (grasshopper_w128_t *) iv;
569
570     // full parts
571     for (i = 0; i < blocks; i++) {
572         currentInputBlock = (grasshopper_w128_t *) current_in;
573         currentOutputBlock = (grasshopper_w128_t *) current_out;
574         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
575                                   &c->partial_buffer, &c->c.buffer);
576         grasshopper_plus128(&tmp, &c->partial_buffer, currentInputBlock);
577         grasshopper_copy128(currentOutputBlock, &tmp);
578         ctr128_inc(iv_buffer->b);
579         current_in += GRASSHOPPER_BLOCK_SIZE;
580         current_out += GRASSHOPPER_BLOCK_SIZE;
581                                 lasted -= GRASSHOPPER_BLOCK_SIZE;
582     }
583
584     if (lasted > 0) {
585         currentInputBlock = (grasshopper_w128_t *) current_in;
586         currentOutputBlock = (grasshopper_w128_t *) current_out;
587         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
588                                   &c->partial_buffer, &c->c.buffer);
589         for (i = 0; i < lasted; i++) {
590             currentOutputBlock->b[i] =
591                 c->partial_buffer.b[i] ^ currentInputBlock->b[i];
592         }
593         EVP_CIPHER_CTX_set_num(ctx, i);
594         ctr128_inc(iv_buffer->b);
595     }
596
597     return inl;
598 }
599
600 #define GRASSHOPPER_BLOCK_MASK (GRASSHOPPER_BLOCK_SIZE - 1)
601 static inline void apply_acpkm_grasshopper(gost_grasshopper_cipher_ctx_ctr *
602                                            ctx, unsigned int *num)
603 {
604     if (!ctx->section_size || (*num < ctx->section_size))
605         return;
606     acpkm_next(&ctx->c);
607     *num &= GRASSHOPPER_BLOCK_MASK;
608 }
609
610 /* If meshing is not configured via ctrl (setting section_size)
611  * this function works exactly like plain ctr */
612 int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx,
613                                         unsigned char *out,
614                                         const unsigned char *in, size_t inl)
615 {
616     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
617     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
618     unsigned int num = EVP_CIPHER_CTX_num(ctx);
619     size_t blocks, i, lasted = inl;
620     grasshopper_w128_t tmp;
621
622     while ((num & GRASSHOPPER_BLOCK_MASK) && lasted) {
623         *out++ = *in++ ^ c->partial_buffer.b[num & GRASSHOPPER_BLOCK_MASK];
624         --lasted;
625         num++;
626     }
627     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
628
629     // full parts
630     for (i = 0; i < blocks; i++) {
631         apply_acpkm_grasshopper(c, &num);
632         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
633                                   (grasshopper_w128_t *) iv,
634                                   (grasshopper_w128_t *) & c->partial_buffer,
635                                   &c->c.buffer);
636         grasshopper_plus128(&tmp, &c->partial_buffer,
637                             (grasshopper_w128_t *) in);
638         grasshopper_copy128((grasshopper_w128_t *) out, &tmp);
639         ctr128_inc(iv);
640         in += GRASSHOPPER_BLOCK_SIZE;
641         out += GRASSHOPPER_BLOCK_SIZE;
642         num += GRASSHOPPER_BLOCK_SIZE;
643                                 lasted -= GRASSHOPPER_BLOCK_SIZE;
644     }
645
646     // last part
647     if (lasted > 0) {
648         apply_acpkm_grasshopper(c, &num);
649         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
650                                   (grasshopper_w128_t *) iv,
651                                   &c->partial_buffer, &c->c.buffer);
652         for (i = 0; i < lasted; i++)
653             out[i] = c->partial_buffer.b[i] ^ in[i];
654         ctr128_inc(iv);
655         num += lasted;
656     }
657     EVP_CIPHER_CTX_set_num(ctx, num);
658
659     return inl;
660 }
661
662 int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx,
663                                         unsigned char *out,
664                                         const unsigned char *in, size_t inl)
665 {
666         int result;
667   gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
668         /* As in and out can be the same pointer, process unencrypted here */
669         if (EVP_CIPHER_CTX_encrypting(ctx))
670                 EVP_DigestSignUpdate(c->omac_ctx, in, inl);
671
672         if (in == NULL && inl == 0) { /* Final call */
673                 return gost2015_final_call(ctx, c->omac_ctx, KUZNYECHIK_MAC_MAX_SIZE, c->tag, gost_grasshopper_cipher_do_ctracpkm);
674         }
675
676   if (in == NULL) {
677       GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_DO_CTRACPKM_OMAC, ERR_R_EVP_LIB);
678       return -1;
679   }
680         result = gost_grasshopper_cipher_do_ctracpkm(ctx, out, in, inl);
681
682         /* As in and out can be the same pointer, process decrypted here */
683         if (!EVP_CIPHER_CTX_encrypting(ctx))
684                 EVP_DigestSignUpdate(c->omac_ctx, out, inl);
685
686         return result;
687 }
688 /*
689  * Fixed 128-bit IV implementation make shift regiser redundant.
690  */
691 static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx * ctx,
692                                       grasshopper_w128_t * iv,
693                                       grasshopper_w128_t * buf)
694 {
695     grasshopper_w128_t tmp;
696     memcpy(&tmp, iv, 16);
697     grasshopper_encrypt_block(&ctx->encrypt_round_keys, &tmp,
698                               buf, &ctx->buffer);
699     memcpy(iv, buf, 16);
700 }
701
702 int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out,
703                                    const unsigned char *in, size_t inl)
704 {
705     gost_grasshopper_cipher_ctx *c = (gost_grasshopper_cipher_ctx *)
706         EVP_CIPHER_CTX_get_cipher_data(ctx);
707     const unsigned char *in_ptr = in;
708     unsigned char *out_ptr = out;
709     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
710     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
711     int num = EVP_CIPHER_CTX_num(ctx);
712     size_t i = 0;
713     size_t j;
714
715     /* process partial block if any */
716     if (num > 0) {
717         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
718              j++, i++, in_ptr++, out_ptr++) {
719             *out_ptr = buf[j] ^ (*in_ptr);
720         }
721         if (j == GRASSHOPPER_BLOCK_SIZE) {
722             EVP_CIPHER_CTX_set_num(ctx, 0);
723         } else {
724             EVP_CIPHER_CTX_set_num(ctx, (int)j);
725             return 1;
726         }
727     }
728
729     for (; i + GRASSHOPPER_BLOCK_SIZE <
730          inl;
731          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
732          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
733         /*
734          * block cipher current iv
735          */
736         /* Encrypt */
737         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
738                                   (grasshopper_w128_t *) buf);
739
740         /*
741          * xor next block of input text with it and output it
742          */
743         /*
744          * output this block
745          */
746         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
747             out_ptr[j] = buf[j] ^ in_ptr[j];
748         }
749     }
750
751     /* Process rest of buffer */
752     if (i < inl) {
753         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
754                                   (grasshopper_w128_t *) buf);
755         for (j = 0; i < inl; j++, i++) {
756             out_ptr[j] = buf[j] ^ in_ptr[j];
757         }
758         EVP_CIPHER_CTX_set_num(ctx, (int)j);
759     } else {
760         EVP_CIPHER_CTX_set_num(ctx, 0);
761     }
762
763     return 1;
764 }
765
766 int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
767                                    const unsigned char *in, size_t inl)
768 {
769     gost_grasshopper_cipher_ctx *c =
770         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
771     const unsigned char *in_ptr = in;
772     unsigned char *out_ptr = out;
773     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
774     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
775     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
776     int num = EVP_CIPHER_CTX_num(ctx);
777     size_t i = 0;
778     size_t j = 0;
779
780     /* process partial block if any */
781     if (num > 0) {
782         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
783              j++, i++, in_ptr++, out_ptr++) {
784             if (!encrypting) {
785                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
786             }
787             *out_ptr = buf[j] ^ (*in_ptr);
788             if (encrypting) {
789                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
790             }
791         }
792         if (j == GRASSHOPPER_BLOCK_SIZE) {
793             memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE);
794             EVP_CIPHER_CTX_set_num(ctx, 0);
795         } else {
796             EVP_CIPHER_CTX_set_num(ctx, (int)j);
797             return 1;
798         }
799     }
800
801     for (; i + GRASSHOPPER_BLOCK_SIZE <
802          inl;
803          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
804          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
805         /*
806          * block cipher current iv
807          */
808         grasshopper_encrypt_block(&c->encrypt_round_keys,
809                                   (grasshopper_w128_t *) iv,
810                                   (grasshopper_w128_t *) buf, &c->buffer);
811         /*
812          * xor next block of input text with it and output it
813          */
814         /*
815          * output this block
816          */
817         if (!encrypting) {
818             memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
819         }
820         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
821             out_ptr[j] = buf[j] ^ in_ptr[j];
822         }
823         /* Encrypt */
824         /* Next iv is next block of cipher text */
825         if (encrypting) {
826             memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
827         }
828     }
829
830     /* Process rest of buffer */
831     if (i < inl) {
832         grasshopper_encrypt_block(&c->encrypt_round_keys,
833                                   (grasshopper_w128_t *) iv,
834                                   (grasshopper_w128_t *) buf, &c->buffer);
835         if (!encrypting) {
836             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
837         }
838         for (j = 0; i < inl; j++, i++) {
839             out_ptr[j] = buf[j] ^ in_ptr[j];
840         }
841         EVP_CIPHER_CTX_set_num(ctx, (int)j);
842         if (encrypting) {
843             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
844         }
845     } else {
846         EVP_CIPHER_CTX_set_num(ctx, 0);
847     }
848
849     return 1;
850 }
851
852 int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX *ctx)
853 {
854     struct GRASSHOPPER_CIPHER_PARAMS *params;
855     gost_grasshopper_cipher_ctx *c =
856         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
857
858     if (!c)
859         return 1;
860
861     params = &gost_cipher_params[c->type];
862
863     gost_grasshopper_cipher_destroy(c);
864     if (params->destroy_cipher != NULL) {
865         params->destroy_cipher(c);
866     }
867
868     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
869
870     return 1;
871 }
872
873 int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
874 {
875         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
876                 gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
877
878                 /* CMS implies 256kb section_size */
879                 ctr->section_size = 256*1024;
880
881                 return gost2015_set_asn1_params(params, EVP_CIPHER_CTX_original_iv(ctx), 8,
882                                 ctr->kdf_seed);
883         }
884         return 0;
885 }
886
887 GRASSHOPPER_INLINE int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX
888                                                             *ctx, ASN1_TYPE
889                                                             *params)
890 {
891         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
892                 gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
893
894                 int iv_len = 16;
895                 unsigned char iv[16];
896
897                 if (gost2015_get_asn1_params(params, 16, iv, 8, ctr->kdf_seed) == 0) {
898                         return 0;
899                 }
900
901                 memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, iv_len);
902                 memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, iv_len);
903
904                 /* CMS implies 256kb section_size */
905                 ctr->section_size = 256*1024;
906                 return 1;
907         }
908         return 0;
909 }
910
911 int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
912 {
913     switch (type) {
914     case EVP_CTRL_RAND_KEY:{
915             if (RAND_priv_bytes
916                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
917                 GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, GOST_R_RNG_ERROR);
918                 return -1;
919             }
920             break;
921         }
922     case EVP_CTRL_KEY_MESH:{
923             gost_grasshopper_cipher_ctx_ctr *c =
924                 EVP_CIPHER_CTX_get_cipher_data(ctx);
925             if ((c->c.type != GRASSHOPPER_CIPHER_CTRACPKM &&
926                                                     c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
927                                                     || (arg == 0)
928                 || (arg % GRASSHOPPER_BLOCK_SIZE))
929                 return -1;
930             c->section_size = arg;
931             break;
932         }
933 #ifdef EVP_CTRL_TLS1_2_TLSTREE
934     case EVP_CTRL_TLS1_2_TLSTREE:
935         {
936           unsigned char newkey[32];
937           int mode = EVP_CIPHER_CTX_mode(ctx);
938           static const unsigned char zeroseq[8];
939           gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL;
940           gost_grasshopper_cipher_ctx *c = NULL;
941
942           unsigned char adjusted_iv[16];
943           unsigned char seq[8];
944           int j, carry;
945           if (mode != EVP_CIPH_CTR_MODE)
946             return -1;
947
948           ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *)
949             EVP_CIPHER_CTX_get_cipher_data(ctx);
950           c = &(ctr_ctx->c);
951
952           memcpy(seq, ptr, 8);
953           if (EVP_CIPHER_CTX_encrypting(ctx)) {
954             /*
955              * OpenSSL increments seq after mac calculation.
956              * As we have Mac-Then-Encrypt, we need decrement it here on encryption
957              * to derive the key correctly.
958              * */
959             if (memcmp(seq, zeroseq, 8) != 0)
960             {
961               for(j=7; j>=0; j--)
962               {
963                 if (seq[j] != 0) {seq[j]--; break;}
964                 else seq[j]  = 0xFF;
965               }
966             }
967           }
968           if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey,
969                 (const unsigned char *)seq) > 0) {
970             memset(adjusted_iv, 0, 16);
971             memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8);
972             for(j=7,carry=0; j>=0; j--)
973             {
974               int adj_byte = adjusted_iv[j]+seq[j]+carry;
975               carry = (adj_byte > 255) ? 1 : 0;
976               adjusted_iv[j] = adj_byte & 0xFF;
977             }
978             EVP_CIPHER_CTX_set_num(ctx, 0);
979             memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 16);
980
981             gost_grasshopper_cipher_key(c, newkey);
982             return 1;
983           }
984         }
985         return -1;
986 #endif
987 #if 0
988     case EVP_CTRL_AEAD_GET_TAG:
989     case EVP_CTRL_AEAD_SET_TAG:
990         {
991             int taglen = arg;
992             unsigned char *tag = ptr;
993
994             gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
995             if (c->c.type != GRASSHOPPER_CIPHER_MGM)
996                 return -1;
997
998             if (taglen > KUZNYECHIK_MAC_MAX_SIZE) {
999                 CRYPTOCOMerr(CRYPTOCOM_F_GOST_GRASSHOPPER_CIPHER_CTL,
1000                         CRYPTOCOM_R_INVALID_TAG_LENGTH);
1001                 return -1;
1002             }
1003
1004             if (type == EVP_CTRL_AEAD_GET_TAG)
1005                 memcpy(tag, c->final_tag, taglen);
1006             else
1007                 memcpy(c->final_tag, tag, taglen);
1008
1009             return 1;
1010         }
1011 #endif
1012                 case EVP_CTRL_PROCESS_UNPROTECTED:
1013     {
1014       STACK_OF(X509_ATTRIBUTE) *x = ptr;
1015       gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
1016
1017       if (c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
1018         return -1;
1019
1020       return gost2015_process_unprotected_attributes(x, arg, KUZNYECHIK_MAC_MAX_SIZE, c->tag);
1021     }
1022     return 1;
1023     case EVP_CTRL_COPY: {
1024                         EVP_CIPHER_CTX *out = ptr;
1025
1026       gost_grasshopper_cipher_ctx_ctr *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out);
1027       gost_grasshopper_cipher_ctx_ctr *in_cctx  = EVP_CIPHER_CTX_get_cipher_data(ctx);
1028
1029       if (in_cctx->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
1030           return -1;
1031
1032                         if (in_cctx->omac_ctx == out_cctx->omac_ctx) {
1033                                 out_cctx->omac_ctx = EVP_MD_CTX_new();
1034                                 if (out_cctx->omac_ctx == NULL) {
1035                                         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, ERR_R_MALLOC_FAILURE);
1036                                         return -1;
1037                                 }
1038                         }
1039                         return EVP_MD_CTX_copy(out_cctx->omac_ctx, in_cctx->omac_ctx);
1040                 }
1041     default:
1042         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL,
1043                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
1044         return -1;
1045     }
1046     return 1;
1047 }
1048
1049 GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_create(int
1050                                                               cipher_type, int
1051                                                               block_size)
1052 {
1053     return EVP_CIPHER_meth_new(cipher_type, block_size /* block_size */ ,
1054                                GRASSHOPPER_KEY_SIZE /* key_size */ );
1055 }
1056
1057 const int cipher_gost_grasshopper_setup(EVP_CIPHER *cipher, uint8_t mode,
1058                                         int iv_size, bool padding, int extra_flags)
1059 {
1060         unsigned long flags = (unsigned long)(mode
1061                  | ((!padding) ?  EVP_CIPH_NO_PADDING : 0)
1062                                          | ((iv_size >  0) ?  EVP_CIPH_CUSTOM_IV : 0)
1063                                          | EVP_CIPH_RAND_KEY |  EVP_CIPH_ALWAYS_CALL_INIT
1064                                          | extra_flags);
1065
1066     return EVP_CIPHER_meth_set_iv_length(cipher, iv_size)
1067         && EVP_CIPHER_meth_set_flags(cipher, flags)
1068         && EVP_CIPHER_meth_set_cleanup(cipher, gost_grasshopper_cipher_cleanup)
1069         && EVP_CIPHER_meth_set_set_asn1_params(cipher,
1070                                                gost_grasshopper_set_asn1_parameters)
1071         && EVP_CIPHER_meth_set_get_asn1_params(cipher,
1072                                                gost_grasshopper_get_asn1_parameters)
1073         && EVP_CIPHER_meth_set_ctrl(cipher, gost_grasshopper_cipher_ctl)
1074         && EVP_CIPHER_meth_set_do_cipher(cipher, gost_grasshopper_cipher_do);
1075 }
1076
1077 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper(uint8_t mode,
1078                                                              uint8_t num)
1079 {
1080     EVP_CIPHER **cipher;
1081     struct GRASSHOPPER_CIPHER_PARAMS *params;
1082
1083     cipher = &gost_grasshopper_ciphers[num];
1084
1085     if (*cipher == NULL) {
1086         grasshopper_init_cipher_func init_cipher;
1087         int nid, block_size, ctx_size, iv_size, extra_flags;
1088         bool padding;
1089
1090         params = &gost_cipher_params[num];
1091
1092         nid = params->nid;
1093         init_cipher = params->init_cipher;
1094         block_size = params->block_size;
1095         ctx_size = params->ctx_size;
1096         iv_size = params->iv_size;
1097         padding = params->padding;
1098                                 extra_flags = params->extra_flags;
1099
1100         *cipher = cipher_gost_grasshopper_create(nid, block_size);
1101         if (*cipher == NULL) {
1102             return NULL;
1103         }
1104
1105         if (!cipher_gost_grasshopper_setup(*cipher, mode, iv_size, padding, extra_flags)
1106             || !EVP_CIPHER_meth_set_init(*cipher, init_cipher)
1107             || !EVP_CIPHER_meth_set_impl_ctx_size(*cipher, ctx_size)) {
1108             EVP_CIPHER_meth_free(*cipher);
1109             *cipher = NULL;
1110         }
1111     }
1112
1113     return *cipher;
1114 }
1115
1116 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ecb()
1117 {
1118     return cipher_gost_grasshopper(EVP_CIPH_ECB_MODE, GRASSHOPPER_CIPHER_ECB);
1119 }
1120
1121 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_cbc()
1122 {
1123     return cipher_gost_grasshopper(EVP_CIPH_CBC_MODE, GRASSHOPPER_CIPHER_CBC);
1124 }
1125
1126 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ofb()
1127 {
1128     return cipher_gost_grasshopper(EVP_CIPH_OFB_MODE, GRASSHOPPER_CIPHER_OFB);
1129 }
1130
1131 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_cfb()
1132 {
1133     return cipher_gost_grasshopper(EVP_CIPH_CFB_MODE, GRASSHOPPER_CIPHER_CFB);
1134 }
1135
1136 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctr()
1137 {
1138     return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE, GRASSHOPPER_CIPHER_CTR);
1139 }
1140
1141 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctracpkm()
1142 {
1143     return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE,
1144                                    GRASSHOPPER_CIPHER_CTRACPKM);
1145 }
1146
1147 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctracpkm_omac()
1148 {
1149     return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE,
1150                                    GRASSHOPPER_CIPHER_CTRACPKMOMAC);
1151 }
1152
1153 void cipher_gost_grasshopper_destroy(void)
1154 {
1155     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB]);
1156     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB] = NULL;
1157     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC]);
1158     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC] = NULL;
1159     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB]);
1160     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB] = NULL;
1161     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB]);
1162     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB] = NULL;
1163     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR]);
1164     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR] = NULL;
1165     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTRACPKM]);
1166     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTRACPKM] = NULL;
1167     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTRACPKMOMAC]);
1168     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTRACPKMOMAC] = NULL;
1169 }
1170 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */