]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
Formatting
[openssl-gost/engine.git] / gost_grasshopper_cipher.c
1 /*
2  * Maxim Tishkov 2016
3  * This file is distributed under the same license as OpenSSL
4  */
5
6 #if defined(__cplusplus)
7 extern "C" {
8 #endif
9
10 #include "gost_grasshopper_cipher.h"
11 #include "gost_grasshopper_defines.h"
12 #include "gost_grasshopper_math.h"
13 #include "gost_grasshopper_core.h"
14
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include <openssl/err.h>
18 #include <string.h>
19
20 #include "gost_lcl.h"
21 #include "e_gost_err.h"
22
23     enum GRASSHOPPER_CIPHER_TYPE {
24         GRASSHOPPER_CIPHER_ECB = 0,
25         GRASSHOPPER_CIPHER_CBC,
26         GRASSHOPPER_CIPHER_OFB,
27         GRASSHOPPER_CIPHER_CFB,
28         GRASSHOPPER_CIPHER_CTR,
29         GRASSHOPPER_CIPHER_CTRACPKM,
30     };
31
32     static EVP_CIPHER *gost_grasshopper_ciphers[6] = {
33         [GRASSHOPPER_CIPHER_ECB] = NULL,
34         [GRASSHOPPER_CIPHER_CBC] = NULL,
35         [GRASSHOPPER_CIPHER_OFB] = NULL,
36         [GRASSHOPPER_CIPHER_CFB] = NULL,
37         [GRASSHOPPER_CIPHER_CTR] = NULL,
38         [GRASSHOPPER_CIPHER_CTRACPKM] = NULL,
39     };
40
41     static GRASSHOPPER_INLINE void
42         gost_grasshopper_cipher_destroy_ofb(gost_grasshopper_cipher_ctx * c);
43     static GRASSHOPPER_INLINE void
44         gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c);
45
46     struct GRASSHOPPER_CIPHER_PARAMS {
47         int nid;
48         grasshopper_init_cipher_func init_cipher;
49         grasshopper_do_cipher_func do_cipher;
50         grasshopper_destroy_cipher_func destroy_cipher;
51         int block_size;
52         int ctx_size;
53         int iv_size;
54         bool padding;
55     };
56
57     static struct GRASSHOPPER_CIPHER_PARAMS gost_cipher_params[6] = {
58         [GRASSHOPPER_CIPHER_ECB] = {
59                                     NID_grasshopper_ecb,
60                                     gost_grasshopper_cipher_init_ecb,
61                                     gost_grasshopper_cipher_do_ecb,
62                                     NULL,
63                                     16,
64                                     sizeof(gost_grasshopper_cipher_ctx),
65                                     0,
66                                     true}
67         ,
68         [GRASSHOPPER_CIPHER_CBC] = {
69                                     NID_grasshopper_cbc,
70                                     gost_grasshopper_cipher_init_cbc,
71                                     gost_grasshopper_cipher_do_cbc,
72                                     NULL,
73                                     16,
74                                     sizeof(gost_grasshopper_cipher_ctx),
75                                     16,
76                                     true}
77         ,
78         [GRASSHOPPER_CIPHER_OFB] = {
79                                     NID_grasshopper_ofb,
80                                     gost_grasshopper_cipher_init_ofb,
81                                     gost_grasshopper_cipher_do_ofb,
82                                     gost_grasshopper_cipher_destroy_ofb,
83                                     1,
84                                     sizeof(gost_grasshopper_cipher_ctx_ofb),
85                                     16,
86                                     false}
87         ,
88         [GRASSHOPPER_CIPHER_CFB] = {
89                                     NID_grasshopper_cfb,
90                                     gost_grasshopper_cipher_init_cfb,
91                                     gost_grasshopper_cipher_do_cfb,
92                                     NULL,
93                                     1,
94                                     sizeof(gost_grasshopper_cipher_ctx),
95                                     16,
96                                     false}
97         ,
98         [GRASSHOPPER_CIPHER_CTR] = {
99                                     NID_grasshopper_ctr,
100                                     gost_grasshopper_cipher_init_ctr,
101                                     gost_grasshopper_cipher_do_ctr,
102                                     gost_grasshopper_cipher_destroy_ctr,
103                                     1,
104                                     sizeof(gost_grasshopper_cipher_ctx_ctr),
105                                     /* IV size is set to match full block, to make it responsibility of
106                                      * user to assign correct values (IV || 0), and to make naive context
107                                      * copy possible (for software such as openssh) */
108                                     16,
109                                     false}
110         ,
111         [GRASSHOPPER_CIPHER_CTRACPKM] = {
112                                          NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
113                                          gost_grasshopper_cipher_init_ctracpkm,
114                                          gost_grasshopper_cipher_do_ctracpkm,
115                                          gost_grasshopper_cipher_destroy_ctr,
116                                          1,
117                                          sizeof
118                                          (gost_grasshopper_cipher_ctx_ctr),
119                                          16,
120                                          false}
121         ,
122     };
123
124 /* first 256 bit of D from draft-irtf-cfrg-re-keying-12 */
125     static const unsigned char ACPKM_D_2018[] = {
126         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /*  64 bit */
127         0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 128 bit */
128         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
129         0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 256 bit */
130     };
131
132     static void acpkm_next(gost_grasshopper_cipher_ctx * c) {
133         unsigned char newkey[GRASSHOPPER_KEY_SIZE];
134         const int J = GRASSHOPPER_KEY_SIZE / GRASSHOPPER_BLOCK_SIZE;
135         int n;
136
137         for (n = 0; n < J; n++) {
138             const unsigned char *D_n =
139                 &ACPKM_D_2018[n * GRASSHOPPER_BLOCK_SIZE];
140
141             grasshopper_encrypt_block(&c->encrypt_round_keys,
142                                       (grasshopper_w128_t *) D_n,
143                                       (grasshopper_w128_t *) & newkey[n *
144                                                                       GRASSHOPPER_BLOCK_SIZE],
145                                       &c->buffer);
146         }
147         gost_grasshopper_cipher_key(c, newkey);
148     }
149
150 /* Set 256 bit  key into context */
151     GRASSHOPPER_INLINE void
152         gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx * c,
153                                     const uint8_t *k) {
154         int i;
155         for (i = 0; i < 2; i++) {
156             grasshopper_copy128(&c->key.k.k[i],
157                                 (const grasshopper_w128_t *)(k + i * 16));
158         }
159         grasshopper_set_encrypt_key(&c->encrypt_round_keys, &c->key);
160         grasshopper_set_decrypt_key(&c->decrypt_round_keys, &c->key);
161     }
162
163 /* Cleans up key from context */
164     GRASSHOPPER_INLINE void
165         gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx * c) {
166         int i;
167         for (i = 0; i < 2; i++) {
168             grasshopper_zero128(&c->key.k.k[i]);
169         }
170         for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
171             grasshopper_zero128(&c->encrypt_round_keys.k[i]);
172         }
173         for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
174             grasshopper_zero128(&c->decrypt_round_keys.k[i]);
175         }
176         grasshopper_zero128(&c->buffer);
177     }
178
179     static GRASSHOPPER_INLINE void
180         gost_grasshopper_cipher_destroy_ofb(gost_grasshopper_cipher_ctx * c) {
181         gost_grasshopper_cipher_ctx_ofb *ctx =
182             (gost_grasshopper_cipher_ctx_ofb *) c;
183
184         grasshopper_zero128(&ctx->buffer1);
185     }
186
187     static GRASSHOPPER_INLINE void
188         gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c) {
189         gost_grasshopper_cipher_ctx_ctr *ctx =
190             (gost_grasshopper_cipher_ctx_ctr *) c;
191
192         grasshopper_zero128(&ctx->partial_buffer);
193     }
194
195     int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx,
196                                      const unsigned char *key,
197                                      const unsigned char *iv, int enc) {
198         gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
199
200         if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
201             EVP_CIPHER_CTX_set_app_data(ctx,
202                                         EVP_CIPHER_CTX_get_cipher_data(ctx));
203         }
204
205         if (key != NULL) {
206             gost_grasshopper_cipher_key(c, key);
207         }
208
209         if (iv != NULL) {
210             memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
211                    EVP_CIPHER_CTX_iv_length(ctx));
212         }
213
214         memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
215                EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
216
217         grasshopper_zero128(&c->buffer);
218
219         return 1;
220     }
221
222     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX *ctx,
223                                                             const unsigned char
224                                                             *key,
225                                                             const unsigned char
226                                                             *iv, int enc) {
227         gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
228         c->type = GRASSHOPPER_CIPHER_ECB;
229         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
230     }
231
232     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX *ctx,
233                                                             const unsigned char
234                                                             *key,
235                                                             const unsigned char
236                                                             *iv, int enc) {
237         gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
238         c->type = GRASSHOPPER_CIPHER_CBC;
239         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
240     }
241
242     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX *ctx,
243                                                             const unsigned char
244                                                             *key,
245                                                             const unsigned char
246                                                             *iv, int enc) {
247         gost_grasshopper_cipher_ctx_ofb *c =
248             EVP_CIPHER_CTX_get_cipher_data(ctx);
249
250         c->c.type = GRASSHOPPER_CIPHER_OFB;
251
252         grasshopper_zero128(&c->buffer1);
253
254         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
255     }
256
257     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX *ctx,
258                                                             const unsigned char
259                                                             *key,
260                                                             const unsigned char
261                                                             *iv, int enc) {
262         gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
263         c->type = GRASSHOPPER_CIPHER_CFB;
264         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
265     }
266
267     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx,
268                                                             const unsigned char
269                                                             *key,
270                                                             const unsigned char
271                                                             *iv, int enc) {
272         gost_grasshopper_cipher_ctx_ctr *c =
273             EVP_CIPHER_CTX_get_cipher_data(ctx);
274
275         c->c.type = GRASSHOPPER_CIPHER_CTR;
276         EVP_CIPHER_CTX_set_num(ctx, 0);
277
278         grasshopper_zero128(&c->partial_buffer);
279
280         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
281     }
282
283     GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX
284                                                                  *ctx,
285                                                                  const unsigned
286                                                                  char *key,
287                                                                  const unsigned
288                                                                  char *iv,
289                                                                  int enc) {
290         gost_grasshopper_cipher_ctx_ctr *c =
291             EVP_CIPHER_CTX_get_cipher_data(ctx);
292
293         /* NB: setting type makes EVP do_cipher callback useless */
294         c->c.type = GRASSHOPPER_CIPHER_CTRACPKM;
295         EVP_CIPHER_CTX_set_num(ctx, 0);
296         c->section_size = 4096;
297
298         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
299     }
300
301     GRASSHOPPER_INLINE int gost_grasshopper_cipher_do(EVP_CIPHER_CTX *ctx,
302                                                       unsigned char *out,
303                                                       const unsigned char *in,
304                                                       size_t inl) {
305         gost_grasshopper_cipher_ctx *c =
306             (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
307         struct GRASSHOPPER_CIPHER_PARAMS *params = &gost_cipher_params[c->type];
308
309         return params->do_cipher(ctx, out, in, inl);
310     }
311
312     int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
313                                        const unsigned char *in, size_t inl) {
314         gost_grasshopper_cipher_ctx *c =
315             (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
316         bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
317         const unsigned char *current_in = in;
318         unsigned char *current_out = out;
319         size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
320         size_t i;
321
322         for (i = 0; i < blocks;
323              i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
324              GRASSHOPPER_BLOCK_SIZE) {
325             if (encrypting) {
326                 grasshopper_encrypt_block(&c->encrypt_round_keys,
327                                           (grasshopper_w128_t *) current_in,
328                                           (grasshopper_w128_t *) current_out,
329                                           &c->buffer);
330             } else {
331                 grasshopper_decrypt_block(&c->decrypt_round_keys,
332                                           (grasshopper_w128_t *) current_in,
333                                           (grasshopper_w128_t *) current_out,
334                                           &c->buffer);
335             }
336         }
337
338         return 1;
339     }
340
341     int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
342                                        const unsigned char *in, size_t inl) {
343         gost_grasshopper_cipher_ctx *c =
344             (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
345         unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
346         bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
347         const unsigned char *current_in = in;
348         unsigned char *current_out = out;
349         grasshopper_w128_t *currentInputBlock;
350         grasshopper_w128_t *currentOutputBlock;
351         size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
352         size_t i;
353         grasshopper_w128_t *currentBlock;
354
355         currentBlock = (grasshopper_w128_t *) iv;
356
357         for (i = 0; i < blocks;
358              i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
359              GRASSHOPPER_BLOCK_SIZE) {
360             currentInputBlock = (grasshopper_w128_t *) current_in;
361             currentOutputBlock = (grasshopper_w128_t *) current_out;
362             if (encrypting) {
363                 grasshopper_append128(currentBlock, currentInputBlock);
364                 grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock,
365                                           currentOutputBlock, &c->buffer);
366                 grasshopper_copy128(currentBlock, currentOutputBlock);
367             } else {
368                 grasshopper_decrypt_block(&c->decrypt_round_keys,
369                                           currentInputBlock, currentOutputBlock,
370                                           &c->buffer);
371                 grasshopper_append128(currentOutputBlock, currentBlock);
372                 grasshopper_copy128(currentBlock, currentInputBlock);
373             }
374         }
375
376         return 1;
377     }
378
379     void inc_counter(unsigned char *counter, size_t counter_bytes) {
380         unsigned char c;
381         unsigned int n = counter_bytes;
382
383         do {
384             --n;
385             c = counter[n];
386             ++c;
387             counter[n] = c;
388             if (c)
389                 return;
390         } while (n);
391     }
392
393 /* increment counter (128-bit int) by 1 */
394     static void ctr128_inc(unsigned char *counter) {
395         inc_counter(counter, 16);
396     }
397
398     int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
399                                        const unsigned char *in, size_t inl) {
400         gost_grasshopper_cipher_ctx_ctr *c =
401             (gost_grasshopper_cipher_ctx_ctr *)
402             EVP_CIPHER_CTX_get_cipher_data(ctx);
403         unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
404         const unsigned char *current_in = in;
405         unsigned char *current_out = out;
406         grasshopper_w128_t *currentInputBlock;
407         grasshopper_w128_t *currentOutputBlock;
408         unsigned int n = EVP_CIPHER_CTX_num(ctx);
409         size_t lasted;
410         size_t i;
411
412         while (n && inl) {
413             *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n];
414             --inl;
415             n = (n + 1) % GRASSHOPPER_BLOCK_SIZE;
416         }
417         EVP_CIPHER_CTX_set_num(ctx, n);
418         size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
419
420         grasshopper_w128_t *iv_buffer = (grasshopper_w128_t *) iv;
421
422         // full parts
423         for (i = 0; i < blocks; i++) {
424             currentInputBlock = (grasshopper_w128_t *) current_in;
425             currentOutputBlock = (grasshopper_w128_t *) current_out;
426             grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
427                                       currentOutputBlock, &c->c.buffer);
428             grasshopper_append128(currentOutputBlock, currentInputBlock);
429             ctr128_inc(iv_buffer->b);
430             current_in += GRASSHOPPER_BLOCK_SIZE;
431             current_out += GRASSHOPPER_BLOCK_SIZE;
432         }
433
434         // last part
435         lasted = inl - blocks * GRASSHOPPER_BLOCK_SIZE;
436         if (lasted > 0) {
437             currentInputBlock = (grasshopper_w128_t *) current_in;
438             currentOutputBlock = (grasshopper_w128_t *) current_out;
439             grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
440                                       &c->partial_buffer, &c->c.buffer);
441             for (i = 0; i < lasted; i++) {
442                 currentOutputBlock->b[i] =
443                     c->partial_buffer.b[i] ^ currentInputBlock->b[i];
444             }
445             EVP_CIPHER_CTX_set_num(ctx, i);
446             ctr128_inc(iv_buffer->b);
447         }
448
449         return 1;
450     }
451
452 #define GRASSHOPPER_BLOCK_MASK (GRASSHOPPER_BLOCK_SIZE - 1)
453     static inline void apply_acpkm_grasshopper(gost_grasshopper_cipher_ctx_ctr *
454                                                ctx, unsigned int *num) {
455         if (!ctx->section_size || (*num < ctx->section_size))
456             return;
457         acpkm_next(&ctx->c);
458         *num &= GRASSHOPPER_BLOCK_MASK;
459     }
460
461 /* If meshing is not configured via ctrl (setting section_size)
462  * this function works exactly like plain ctr */
463     int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx,
464                                             unsigned char *out,
465                                             const unsigned char *in,
466                                             size_t inl) {
467         gost_grasshopper_cipher_ctx_ctr *c =
468             EVP_CIPHER_CTX_get_cipher_data(ctx);
469         unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
470         unsigned int num = EVP_CIPHER_CTX_num(ctx);
471
472         while ((num & GRASSHOPPER_BLOCK_MASK) && inl) {
473             *out++ = *in++ ^ c->partial_buffer.b[num & GRASSHOPPER_BLOCK_MASK];
474             --inl;
475             num++;
476         }
477         size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
478         size_t i;
479
480         // full parts
481         for (i = 0; i < blocks; i++) {
482             apply_acpkm_grasshopper(c, &num);
483             grasshopper_encrypt_block(&c->c.encrypt_round_keys,
484                                       (grasshopper_w128_t *) iv,
485                                       (grasshopper_w128_t *) out, &c->c.buffer);
486             grasshopper_append128((grasshopper_w128_t *) out,
487                                   (grasshopper_w128_t *) in);
488             ctr128_inc(iv);
489             in += GRASSHOPPER_BLOCK_SIZE;
490             out += GRASSHOPPER_BLOCK_SIZE;
491             num += GRASSHOPPER_BLOCK_SIZE;
492         }
493
494         // last part
495         size_t lasted = inl - blocks * GRASSHOPPER_BLOCK_SIZE;
496         if (lasted > 0) {
497             apply_acpkm_grasshopper(c, &num);
498             grasshopper_encrypt_block(&c->c.encrypt_round_keys,
499                                       (grasshopper_w128_t *) iv,
500                                       &c->partial_buffer, &c->c.buffer);
501             for (i = 0; i < lasted; i++)
502                 out[i] = c->partial_buffer.b[i] ^ in[i];
503             ctr128_inc(iv);
504             num += lasted;
505         }
506         EVP_CIPHER_CTX_set_num(ctx, num);
507
508         return 1;
509     }
510
511 /*
512  * Fixed 128-bit IV implementation make shift regiser redundant.
513  */
514     static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx_ofb * ctx,
515                                           grasshopper_w128_t * iv,
516                                           grasshopper_w128_t * buf) {
517         memcpy(&ctx->buffer1, iv, 16);
518         grasshopper_encrypt_block(&ctx->c.encrypt_round_keys, &ctx->buffer1,
519                                   buf, &ctx->c.buffer);
520         memcpy(iv, buf, 16);
521     }
522
523     int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out,
524                                        const unsigned char *in, size_t inl) {
525         gost_grasshopper_cipher_ctx_ofb *c =
526             (gost_grasshopper_cipher_ctx_ofb *)
527             EVP_CIPHER_CTX_get_cipher_data(ctx);
528         const unsigned char *in_ptr = in;
529         unsigned char *out_ptr = out;
530         unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
531         unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
532         int num = EVP_CIPHER_CTX_num(ctx);
533         size_t i = 0;
534         size_t j;
535
536         /* process partial block if any */
537         if (num > 0) {
538             for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
539                  j++, i++, in_ptr++, out_ptr++) {
540                 *out_ptr = buf[j] ^ (*in_ptr);
541             }
542             if (j == GRASSHOPPER_BLOCK_SIZE) {
543                 EVP_CIPHER_CTX_set_num(ctx, 0);
544             } else {
545                 EVP_CIPHER_CTX_set_num(ctx, (int)j);
546                 return 1;
547             }
548         }
549
550         for (; i + GRASSHOPPER_BLOCK_SIZE <
551              inl;
552              i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
553              GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
554             /*
555              * block cipher current iv
556              */
557             /* Encrypt */
558             gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
559                                       (grasshopper_w128_t *) buf);
560
561             /*
562              * xor next block of input text with it and output it
563              */
564             /*
565              * output this block
566              */
567             for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
568                 out_ptr[j] = buf[j] ^ in_ptr[j];
569             }
570         }
571
572         /* Process rest of buffer */
573         if (i < inl) {
574             gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
575                                       (grasshopper_w128_t *) buf);
576             for (j = 0; i < inl; j++, i++) {
577                 out_ptr[j] = buf[j] ^ in_ptr[j];
578             }
579             EVP_CIPHER_CTX_set_num(ctx, (int)j);
580         } else {
581             EVP_CIPHER_CTX_set_num(ctx, 0);
582         }
583
584         return 1;
585     }
586
587     int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
588                                        const unsigned char *in, size_t inl) {
589         gost_grasshopper_cipher_ctx *c =
590             (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
591         const unsigned char *in_ptr = in;
592         unsigned char *out_ptr = out;
593         unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
594         unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
595         bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
596         int num = EVP_CIPHER_CTX_num(ctx);
597         size_t i = 0;
598         size_t j = 0;
599
600         /* process partial block if any */
601         if (num > 0) {
602             for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
603                  j++, i++, in_ptr++, out_ptr++) {
604                 if (!encrypting) {
605                     buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
606                 }
607                 *out_ptr = buf[j] ^ (*in_ptr);
608                 if (encrypting) {
609                     buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
610                 }
611             }
612             if (j == GRASSHOPPER_BLOCK_SIZE) {
613                 memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE,
614                        GRASSHOPPER_BLOCK_SIZE);
615                 EVP_CIPHER_CTX_set_num(ctx, 0);
616             } else {
617                 EVP_CIPHER_CTX_set_num(ctx, (int)j);
618                 return 1;
619             }
620         }
621
622         for (; i + GRASSHOPPER_BLOCK_SIZE <
623              inl;
624              i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
625              GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
626             /*
627              * block cipher current iv
628              */
629             grasshopper_encrypt_block(&c->encrypt_round_keys,
630                                       (grasshopper_w128_t *) iv,
631                                       (grasshopper_w128_t *) buf, &c->buffer);
632             /*
633              * xor next block of input text with it and output it
634              */
635             /*
636              * output this block
637              */
638             if (!encrypting) {
639                 memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
640             }
641             for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
642                 out_ptr[j] = buf[j] ^ in_ptr[j];
643             }
644             /* Encrypt */
645             /* Next iv is next block of cipher text */
646             if (encrypting) {
647                 memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
648             }
649         }
650
651         /* Process rest of buffer */
652         if (i < inl) {
653             grasshopper_encrypt_block(&c->encrypt_round_keys,
654                                       (grasshopper_w128_t *) iv,
655                                       (grasshopper_w128_t *) buf, &c->buffer);
656             if (!encrypting) {
657                 memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
658             }
659             for (j = 0; i < inl; j++, i++) {
660                 out_ptr[j] = buf[j] ^ in_ptr[j];
661             }
662             EVP_CIPHER_CTX_set_num(ctx, (int)j);
663             if (encrypting) {
664                 memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
665             }
666         } else {
667             EVP_CIPHER_CTX_set_num(ctx, 0);
668         }
669
670         return 1;
671     }
672
673     int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX *ctx) {
674         gost_grasshopper_cipher_ctx *c =
675             (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
676
677         if (!c)
678             return 1;
679
680         struct GRASSHOPPER_CIPHER_PARAMS *params = &gost_cipher_params[c->type];
681
682         gost_grasshopper_cipher_destroy(c);
683         if (params->destroy_cipher != NULL) {
684             params->destroy_cipher(c);
685         }
686
687         EVP_CIPHER_CTX_set_app_data(ctx, NULL);
688
689         return 1;
690     }
691
692     int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX *ctx,
693                                              ASN1_TYPE *params) {
694         int len = 0;
695         unsigned char *buf = NULL;
696         ASN1_OCTET_STRING *os = NULL;
697
698         os = ASN1_OCTET_STRING_new();
699
700         if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
701             OPENSSL_free(buf);
702             GOSTerr(GOST_F_GOST_GRASSHOPPER_SET_ASN1_PARAMETERS,
703                     ERR_R_MALLOC_FAILURE);
704             return 0;
705         }
706         OPENSSL_free(buf);
707
708         ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
709         return 1;
710     }
711
712     GRASSHOPPER_INLINE int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX
713                                                                 *ctx,
714                                                                 ASN1_TYPE
715                                                                 *params) {
716         int ret = -1;
717
718         if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
719             return ret;
720         }
721
722         return 1;
723     }
724
725     int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg,
726                                     void *ptr) {
727         switch (type) {
728         case EVP_CTRL_RAND_KEY:{
729                 if (RAND_bytes
730                     ((unsigned char *)ptr,
731                      EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
732                     GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL,
733                             GOST_R_RNG_ERROR);
734                     return -1;
735                 }
736                 break;
737             }
738         case EVP_CTRL_KEY_MESH:{
739                 gost_grasshopper_cipher_ctx_ctr *c =
740                     EVP_CIPHER_CTX_get_cipher_data(ctx);
741                 if (c->c.type != GRASSHOPPER_CIPHER_CTRACPKM || !arg
742                     || (arg % GRASSHOPPER_BLOCK_SIZE))
743                     return -1;
744                 c->section_size = arg;
745                 break;
746             }
747         default:
748             GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL,
749                     GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
750             return -1;
751         }
752         return 1;
753     }
754
755     GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_create(int
756                                                                   cipher_type,
757                                                                   int
758                                                                   block_size) {
759         return EVP_CIPHER_meth_new(cipher_type, block_size /* block_size */ ,
760                                    GRASSHOPPER_KEY_SIZE /* key_size */ );
761     }
762
763     const int cipher_gost_grasshopper_setup(EVP_CIPHER *cipher, uint8_t mode,
764                                             int iv_size, bool padding) {
765         return EVP_CIPHER_meth_set_iv_length(cipher, iv_size)
766             && EVP_CIPHER_meth_set_flags(cipher,
767                                          (unsigned long)(mode |
768                                                          ((!padding) ?
769                                                           EVP_CIPH_NO_PADDING :
770                                                           0) | ((iv_size >
771                                                                  0) ?
772                                                                 EVP_CIPH_CUSTOM_IV
773                                                                 : 0) |
774                                                          EVP_CIPH_RAND_KEY |
775                                                          EVP_CIPH_ALWAYS_CALL_INIT)
776             )
777             && EVP_CIPHER_meth_set_cleanup(cipher,
778                                            gost_grasshopper_cipher_cleanup)
779             && EVP_CIPHER_meth_set_set_asn1_params(cipher,
780                                                    gost_grasshopper_set_asn1_parameters)
781             && EVP_CIPHER_meth_set_get_asn1_params(cipher,
782                                                    gost_grasshopper_get_asn1_parameters)
783             && EVP_CIPHER_meth_set_ctrl(cipher, gost_grasshopper_cipher_ctl)
784             && EVP_CIPHER_meth_set_do_cipher(cipher,
785                                              gost_grasshopper_cipher_do);
786     }
787
788     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper(uint8_t mode,
789                                                                  uint8_t num) {
790         EVP_CIPHER **cipher;
791         struct GRASSHOPPER_CIPHER_PARAMS *params;
792
793         cipher = &gost_grasshopper_ciphers[num];
794
795         if (*cipher == NULL) {
796             params = &gost_cipher_params[num];
797
798             int nid = params->nid;
799             grasshopper_init_cipher_func init_cipher = params->init_cipher;
800             int block_size = params->block_size;
801             int ctx_size = params->ctx_size;
802             int iv_size = params->iv_size;
803             bool padding = params->padding;
804
805             *cipher = cipher_gost_grasshopper_create(nid, block_size);
806             if (*cipher == NULL) {
807                 return NULL;
808             }
809
810             if (!cipher_gost_grasshopper_setup(*cipher, mode, iv_size, padding)
811                 || !EVP_CIPHER_meth_set_init(*cipher, init_cipher)
812                 || !EVP_CIPHER_meth_set_impl_ctx_size(*cipher, ctx_size)) {
813                 EVP_CIPHER_meth_free(*cipher);
814                 *cipher = NULL;
815             }
816         }
817
818         return *cipher;
819     }
820
821     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ecb() {
822         return cipher_gost_grasshopper(EVP_CIPH_ECB_MODE,
823                                        GRASSHOPPER_CIPHER_ECB);
824     }
825
826     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_cbc() {
827         return cipher_gost_grasshopper(EVP_CIPH_CBC_MODE,
828                                        GRASSHOPPER_CIPHER_CBC);
829     }
830
831     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ofb() {
832         return cipher_gost_grasshopper(EVP_CIPH_OFB_MODE,
833                                        GRASSHOPPER_CIPHER_OFB);
834     }
835
836     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_cfb() {
837         return cipher_gost_grasshopper(EVP_CIPH_CFB_MODE,
838                                        GRASSHOPPER_CIPHER_CFB);
839     }
840
841     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctr() {
842         return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE,
843                                        GRASSHOPPER_CIPHER_CTR);
844     }
845
846     const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctracpkm() {
847         return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE,
848                                        GRASSHOPPER_CIPHER_CTRACPKM);
849     }
850
851     void cipher_gost_grasshopper_destroy(void) {
852         EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB]);
853         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB] = NULL;
854         EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC]);
855         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC] = NULL;
856         EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB]);
857         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB] = NULL;
858         EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB]);
859         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB] = NULL;
860         EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR]);
861         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR] = NULL;
862         EVP_CIPHER_meth_free(gost_grasshopper_ciphers
863                              [GRASSHOPPER_CIPHER_CTRACPKM]);
864         gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTRACPKM] = NULL;
865     }
866
867 #if defined(__cplusplus)
868 }
869 #endif