]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
gost_crypt: process full available block in CFB and CNT mode
[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 "e_gost_err.h"
21
22 enum GRASSHOPPER_CIPHER_TYPE {
23     GRASSHOPPER_CIPHER_ECB = 0,
24     GRASSHOPPER_CIPHER_CBC,
25     GRASSHOPPER_CIPHER_OFB,
26     GRASSHOPPER_CIPHER_CFB,
27     GRASSHOPPER_CIPHER_CTR
28 };
29
30 static EVP_CIPHER* gost_grasshopper_ciphers[5] = {
31         [GRASSHOPPER_CIPHER_ECB] = NULL,
32         [GRASSHOPPER_CIPHER_CBC] = NULL,
33         [GRASSHOPPER_CIPHER_OFB] = NULL,
34         [GRASSHOPPER_CIPHER_CFB] = NULL,
35         [GRASSHOPPER_CIPHER_CTR] = NULL
36 };
37
38 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ofb(gost_grasshopper_cipher_ctx* c);
39 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx* c);
40
41 struct GRASSHOPPER_CIPHER_PARAMS {
42     int nid;
43     grasshopper_init_cipher_func init_cipher;
44     grasshopper_do_cipher_func do_cipher;
45     grasshopper_destroy_cipher_func destroy_cipher;
46     int block_size;
47     int ctx_size;
48     int iv_size;
49     bool padding;
50 };
51
52 static struct GRASSHOPPER_CIPHER_PARAMS gost_cipher_params[5] = {
53         [GRASSHOPPER_CIPHER_ECB] = {
54                 NID_grasshopper_ecb,
55                 gost_grasshopper_cipher_init_ecb,
56                 gost_grasshopper_cipher_do_ecb,
57                 NULL,
58                 16,
59                 sizeof(gost_grasshopper_cipher_ctx),
60                 0,
61                 true
62         },
63         [GRASSHOPPER_CIPHER_CBC] = {
64                 NID_grasshopper_cbc,
65                 gost_grasshopper_cipher_init_cbc,
66                 gost_grasshopper_cipher_do_cbc,
67                 NULL,
68                 16,
69                 sizeof(gost_grasshopper_cipher_ctx),
70                 16,
71                 true
72         },
73         [GRASSHOPPER_CIPHER_OFB] = {
74                 NID_grasshopper_ofb,
75                 gost_grasshopper_cipher_init_ofb,
76                 gost_grasshopper_cipher_do_ofb,
77                 gost_grasshopper_cipher_destroy_ofb,
78                 1,
79                 sizeof(gost_grasshopper_cipher_ctx_ofb),
80                 16,
81                 false
82         },
83         [GRASSHOPPER_CIPHER_CFB] = {
84                 NID_grasshopper_cfb,
85                 gost_grasshopper_cipher_init_cfb,
86                 gost_grasshopper_cipher_do_cfb,
87                 NULL,
88                 1,
89                 sizeof(gost_grasshopper_cipher_ctx),
90                 16,
91                 false
92         },
93         [GRASSHOPPER_CIPHER_CTR] = {
94                 NID_grasshopper_ctr,
95                 gost_grasshopper_cipher_init_ctr,
96                 gost_grasshopper_cipher_do_ctr,
97                 gost_grasshopper_cipher_destroy_ctr,
98                 1,
99                 sizeof(gost_grasshopper_cipher_ctx_ctr),
100                 /* IV size is set to match full block, to make it responsibility of
101                  * user to assign correct values (IV || 0), and to make naive context
102                  * copy possible (for software such as openssh) */
103                 16,
104                 false
105         },
106 };
107
108 /* Set 256 bit  key into context */
109 GRASSHOPPER_INLINE void gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx* c, const uint8_t* k) {
110                 int i;
111     for (i = 0; i < 2; i++) {
112         grasshopper_copy128(&c->key.k.k[i], (const grasshopper_w128_t*) (k + i * 16));
113     }
114     grasshopper_set_encrypt_key(&c->encrypt_round_keys, &c->key);
115     grasshopper_set_decrypt_key(&c->decrypt_round_keys, &c->key);
116 }
117
118 /* Cleans up key from context */
119 GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx* c) {
120                 int i;
121     for (i = 0; i < 2; i++) {
122         grasshopper_zero128(&c->key.k.k[i]);
123     }
124     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
125         grasshopper_zero128(&c->encrypt_round_keys.k[i]);
126     }
127     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
128         grasshopper_zero128(&c->decrypt_round_keys.k[i]);
129     }
130     grasshopper_zero128(&c->buffer);
131 }
132
133 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ofb(gost_grasshopper_cipher_ctx* c) {
134     gost_grasshopper_cipher_ctx_ofb* ctx = (gost_grasshopper_cipher_ctx_ofb*) c;
135
136     grasshopper_zero128(&ctx->buffer1);
137 }
138
139 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx* c) {
140     gost_grasshopper_cipher_ctx_ctr* ctx = (gost_grasshopper_cipher_ctx_ctr*) c;
141
142     grasshopper_zero128(&ctx->partial_buffer);
143 }
144
145 int gost_grasshopper_cipher_init(EVP_CIPHER_CTX* ctx, const unsigned char* key,
146                                         const unsigned char* iv, int enc) {
147     gost_grasshopper_cipher_ctx* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
148
149     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
150         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
151     }
152
153     if (key != NULL) {
154         gost_grasshopper_cipher_key(c, key);
155     }
156
157     if (iv != NULL) {
158         memcpy((unsigned char*) EVP_CIPHER_CTX_original_iv(ctx), iv,
159                EVP_CIPHER_CTX_iv_length(ctx));
160     }
161
162     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
163            EVP_CIPHER_CTX_original_iv(ctx),
164            EVP_CIPHER_CTX_iv_length(ctx));
165
166     grasshopper_zero128(&c->buffer);
167
168     return 1;
169 }
170
171 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX* ctx, const unsigned char* key,
172                                                                const unsigned char* iv,
173                                                                int enc) {
174     gost_grasshopper_cipher_ctx* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
175     c->type = GRASSHOPPER_CIPHER_ECB;
176     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
177 }
178
179 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX* ctx, const unsigned char* key,
180                                                                const unsigned char* iv,
181                                                                int enc) {
182     gost_grasshopper_cipher_ctx* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
183     c->type = GRASSHOPPER_CIPHER_CBC;
184     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
185 }
186
187 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX* ctx, const unsigned char* key,
188                                                                const unsigned char* iv,
189                                                                int enc) {
190     gost_grasshopper_cipher_ctx_ofb* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
191
192     c->c.type = GRASSHOPPER_CIPHER_OFB;
193
194     grasshopper_zero128(&c->buffer1);
195
196     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
197 }
198
199 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX* ctx, const unsigned char* key,
200                                                                const unsigned char* iv,
201                                                                int enc) {
202     gost_grasshopper_cipher_ctx* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
203     c->type = GRASSHOPPER_CIPHER_CFB;
204     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
205 }
206
207 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX* ctx, const unsigned char* key,
208                                                                const unsigned char* iv,
209                                                                int enc) {
210     gost_grasshopper_cipher_ctx_ctr* c = EVP_CIPHER_CTX_get_cipher_data(ctx);
211
212     c->c.type = GRASSHOPPER_CIPHER_CTR;
213     EVP_CIPHER_CTX_set_num(ctx, 0);
214
215     grasshopper_zero128(&c->partial_buffer);
216
217     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
218 }
219
220 GRASSHOPPER_INLINE int gost_grasshopper_cipher_do(EVP_CIPHER_CTX* ctx, unsigned char* out,
221                                                          const unsigned char* in, size_t inl) {
222     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
223     struct GRASSHOPPER_CIPHER_PARAMS* params = &gost_cipher_params[c->type];
224
225     return params->do_cipher(ctx, out, in, inl);
226 }
227
228 int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX* ctx, unsigned char* out,
229                                           const unsigned char* in, size_t inl) {
230     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
231     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
232     const unsigned char* current_in = in;
233     unsigned char* current_out = out;
234     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
235     size_t i;
236
237     for (i = 0; i < blocks; i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out += GRASSHOPPER_BLOCK_SIZE) {
238         if (encrypting) {
239             grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) current_in,
240                                       (grasshopper_w128_t*) current_out,
241                                       &c->buffer);
242         } else {
243             grasshopper_decrypt_block(&c->decrypt_round_keys, (grasshopper_w128_t*) current_in,
244                                       (grasshopper_w128_t*) current_out,
245                                       &c->buffer);
246         }
247     }
248
249     return 1;
250 }
251
252 int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX* ctx, unsigned char* out,
253                                           const unsigned char* in, size_t inl) {
254     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
255     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
256     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
257     const unsigned char* current_in = in;
258     unsigned char* current_out = out;
259     grasshopper_w128_t* currentInputBlock;
260     grasshopper_w128_t* currentOutputBlock;
261     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
262     size_t i;
263     grasshopper_w128_t* currentBlock;
264
265     currentBlock = (grasshopper_w128_t*) iv;
266
267     for (i = 0; i < blocks; i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out += GRASSHOPPER_BLOCK_SIZE) {
268         currentInputBlock = (grasshopper_w128_t*) current_in;
269         currentOutputBlock = (grasshopper_w128_t*) current_out;
270         if (encrypting) {
271             grasshopper_append128(currentBlock, currentInputBlock);
272             grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock, currentOutputBlock, &c->buffer);
273             grasshopper_copy128(currentBlock, currentOutputBlock);
274         } else {
275             grasshopper_decrypt_block(&c->decrypt_round_keys, currentInputBlock, currentOutputBlock, &c->buffer);
276             grasshopper_append128(currentOutputBlock, currentBlock);
277             grasshopper_copy128(currentBlock, currentInputBlock);
278         }
279     }
280
281     return 1;
282 }
283
284 /* increment counter (128-bit int) by 1 */
285 static void ctr128_inc(unsigned char *counter)
286 {
287     unsigned int n = 16;
288     unsigned char c;
289
290     do {
291         --n;
292         c = counter[n];
293         ++c;
294         counter[n] = c;
295         if (c) return;
296     } while (n);
297 }
298
299 int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out,
300                                           const unsigned char* in, size_t inl) {
301     gost_grasshopper_cipher_ctx_ctr* c = (gost_grasshopper_cipher_ctx_ctr*) EVP_CIPHER_CTX_get_cipher_data(ctx);
302     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
303     const unsigned char* current_in = in;
304     unsigned char* current_out = out;
305     grasshopper_w128_t* currentInputBlock;
306     grasshopper_w128_t* currentOutputBlock;
307     unsigned int n = EVP_CIPHER_CTX_num(ctx);
308     size_t lasted;
309     size_t i;
310
311     while (n && inl) {
312         *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n];
313         --inl;
314         n = (n + 1) % GRASSHOPPER_BLOCK_SIZE;
315     }
316     EVP_CIPHER_CTX_set_num(ctx, n);
317     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
318
319     grasshopper_w128_t* iv_buffer = (grasshopper_w128_t*) iv;
320
321     // full parts
322     for (i = 0; i < blocks; i++) {
323         currentInputBlock = (grasshopper_w128_t*) current_in;
324         currentOutputBlock = (grasshopper_w128_t*) current_out;
325         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer, currentOutputBlock, &c->c.buffer);
326         grasshopper_append128(currentOutputBlock, currentInputBlock);
327         ctr128_inc(iv_buffer->b);
328         current_in += GRASSHOPPER_BLOCK_SIZE;
329         current_out += GRASSHOPPER_BLOCK_SIZE;
330     }
331
332     // last part
333     lasted = inl - blocks * GRASSHOPPER_BLOCK_SIZE;
334     if (lasted > 0) {
335         currentInputBlock = (grasshopper_w128_t*) current_in;
336         currentOutputBlock = (grasshopper_w128_t*) current_out;
337         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer, &c->partial_buffer, &c->c.buffer);
338         for (i = 0; i < lasted; i++) {
339             currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i];
340         }
341         EVP_CIPHER_CTX_set_num(ctx, i);
342         ctr128_inc(iv_buffer->b);
343     }
344
345     return 1;
346 }
347
348 /*
349  * Fixed 128-bit IV implementation make shift regiser redundant.
350  */
351 static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx_ofb* ctx, grasshopper_w128_t* iv,
352                                       grasshopper_w128_t* buf) {
353     memcpy(&ctx->buffer1, iv, 16);
354     grasshopper_encrypt_block(&ctx->c.encrypt_round_keys, &ctx->buffer1, buf, &ctx->c.buffer);
355     memcpy(iv, buf, 16);
356 }
357
358 int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX* ctx, unsigned char* out,
359                                           const unsigned char* in, size_t inl) {
360     gost_grasshopper_cipher_ctx_ofb* c = (gost_grasshopper_cipher_ctx_ofb*) EVP_CIPHER_CTX_get_cipher_data(ctx);
361     const unsigned char* in_ptr = in;
362     unsigned char* out_ptr = out;
363     unsigned char* buf = EVP_CIPHER_CTX_buf_noconst(ctx);
364     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
365     int num = EVP_CIPHER_CTX_num(ctx);
366     size_t i = 0;
367     size_t j;
368
369     /* process partial block if any */
370     if (num > 0) {
371         for (j = (size_t) num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
372              j++, i++, in_ptr++, out_ptr++) {
373             *out_ptr = buf[j] ^ (*in_ptr);
374         }
375         if (j == GRASSHOPPER_BLOCK_SIZE) {
376             EVP_CIPHER_CTX_set_num(ctx, 0);
377         } else {
378             EVP_CIPHER_CTX_set_num(ctx, (int) j);
379             return 1;
380         }
381     }
382
383     for (; i + GRASSHOPPER_BLOCK_SIZE <
384            inl; i += GRASSHOPPER_BLOCK_SIZE, in_ptr += GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
385         /*
386          * block cipher current iv
387          */
388         /* Encrypt */
389         gost_grasshopper_cnt_next(c, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf);
390
391         /*
392          * xor next block of input text with it and output it
393          */
394         /*
395          * output this block
396          */
397         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
398             out_ptr[j] = buf[j] ^ in_ptr[j];
399         }
400     }
401
402     /* Process rest of buffer */
403     if (i < inl) {
404         gost_grasshopper_cnt_next(c, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf);
405         for (j = 0; i < inl; j++, i++) {
406             out_ptr[j] = buf[j] ^ in_ptr[j];
407         }
408         EVP_CIPHER_CTX_set_num(ctx, (int) j);
409     } else {
410         EVP_CIPHER_CTX_set_num(ctx, 0);
411     }
412
413     return 1;
414 }
415
416 int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX* ctx, unsigned char* out,
417                                           const unsigned char* in, size_t inl) {
418     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
419     const unsigned char* in_ptr = in;
420     unsigned char* out_ptr = out;
421     unsigned char* buf = EVP_CIPHER_CTX_buf_noconst(ctx);
422     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
423     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
424     int num = EVP_CIPHER_CTX_num(ctx);
425     size_t i = 0;
426     size_t j = 0;
427
428     /* process partial block if any */
429     if (num > 0) {
430         for (j = (size_t) num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl; j++, i++, in_ptr++, out_ptr++) {
431             if (!encrypting) {
432                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
433             }
434             *out_ptr = buf[j] ^ (*in_ptr);
435             if (encrypting) {
436                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
437             }
438         }
439         if (j == GRASSHOPPER_BLOCK_SIZE) {
440             memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE);
441             EVP_CIPHER_CTX_set_num(ctx, 0);
442         } else {
443             EVP_CIPHER_CTX_set_num(ctx, (int) j);
444             return 1;
445         }
446     }
447
448     for (; i + GRASSHOPPER_BLOCK_SIZE <
449            inl; i += GRASSHOPPER_BLOCK_SIZE, in_ptr += GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
450         /*
451          * block cipher current iv
452          */
453         grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf,
454                                   &c->buffer);
455         /*
456          * xor next block of input text with it and output it
457          */
458         /*
459          * output this block
460          */
461         if (!encrypting) {
462             memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
463         }
464         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
465             out_ptr[j] = buf[j] ^ in_ptr[j];
466         }
467         /* Encrypt */
468         /* Next iv is next block of cipher text */
469         if (encrypting) {
470             memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
471         }
472     }
473
474     /* Process rest of buffer */
475     if (i < inl) {
476         grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf,
477                                   &c->buffer);
478         if (!encrypting) {
479             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
480         }
481         for (j = 0; i < inl; j++, i++) {
482             out_ptr[j] = buf[j] ^ in_ptr[j];
483         }
484         EVP_CIPHER_CTX_set_num(ctx, (int) j);
485         if (encrypting) {
486             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
487         }
488     } else {
489         EVP_CIPHER_CTX_set_num(ctx, 0);
490     }
491
492     return 1;
493 }
494
495 int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX* ctx) {
496     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
497     struct GRASSHOPPER_CIPHER_PARAMS* params = &gost_cipher_params[c->type];
498
499     gost_grasshopper_cipher_destroy(c);
500     if (params->destroy_cipher != NULL) {
501         params->destroy_cipher(c);
502     }
503
504     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
505
506     return 1;
507 }
508
509 int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params) {
510     int len = 0;
511     unsigned char* buf = NULL;
512     ASN1_OCTET_STRING* os = NULL;
513
514     os = ASN1_OCTET_STRING_new();
515
516     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
517         OPENSSL_free(buf);
518         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
519         return 0;
520     }
521     OPENSSL_free(buf);
522
523     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
524     return 1;
525 }
526
527 GRASSHOPPER_INLINE int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params) {
528     int ret = -1;
529
530     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
531         return ret;
532     }
533
534     return 1;
535 }
536
537 int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX* ctx, int type, int arg, void* ptr) {
538     switch (type) {
539         case EVP_CTRL_RAND_KEY: {
540             if (RAND_bytes((unsigned char*) ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
541                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
542                 return -1;
543             }
544             break;
545         }
546         default:
547             GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
548             return -1;
549     }
550     return 1;
551 }
552
553 GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_create(int cipher_type, int block_size) {
554     return EVP_CIPHER_meth_new(cipher_type,
555                                block_size  /* block_size */,
556                                GRASSHOPPER_KEY_SIZE /* key_size */);
557 }
558
559 const int cipher_gost_grasshopper_setup(EVP_CIPHER* cipher, uint8_t mode, int iv_size, bool padding) {
560     return EVP_CIPHER_meth_set_iv_length(cipher, iv_size) &&
561            EVP_CIPHER_meth_set_flags(cipher, (unsigned long) (
562                    mode |
563                    ((!padding) ? EVP_CIPH_NO_PADDING : 0) |
564                    ((iv_size > 0) ? EVP_CIPH_CUSTOM_IV : 0) |
565                    EVP_CIPH_RAND_KEY |
566                    EVP_CIPH_ALWAYS_CALL_INIT)
567            ) &&
568            EVP_CIPHER_meth_set_cleanup(cipher, gost_grasshopper_cipher_cleanup) &&
569            EVP_CIPHER_meth_set_set_asn1_params(cipher, gost_grasshopper_set_asn1_parameters) &&
570            EVP_CIPHER_meth_set_get_asn1_params(cipher, gost_grasshopper_get_asn1_parameters) &&
571            EVP_CIPHER_meth_set_ctrl(cipher, gost_grasshopper_cipher_ctl) &&
572            EVP_CIPHER_meth_set_do_cipher(cipher, gost_grasshopper_cipher_do);
573 }
574
575 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper(uint8_t mode, uint8_t num) {
576     EVP_CIPHER** cipher;
577     struct GRASSHOPPER_CIPHER_PARAMS* params;
578
579     cipher = &gost_grasshopper_ciphers[num];
580
581     if (*cipher == NULL) {
582         params = &gost_cipher_params[num];
583
584         int nid = params->nid;
585         grasshopper_init_cipher_func init_cipher = params->init_cipher;
586         int block_size = params->block_size;
587         int ctx_size = params->ctx_size;
588         int iv_size = params->iv_size;
589         bool padding = params->padding;
590
591         *cipher = cipher_gost_grasshopper_create(nid, block_size);
592         if (*cipher == NULL) {
593             return NULL;
594         }
595
596         if (!cipher_gost_grasshopper_setup(*cipher, mode, iv_size, padding) ||
597             !EVP_CIPHER_meth_set_init(*cipher, init_cipher) ||
598             !EVP_CIPHER_meth_set_impl_ctx_size(*cipher, ctx_size)) {
599             EVP_CIPHER_meth_free(*cipher);
600             *cipher = NULL;
601         }
602     }
603
604     return *cipher;
605 }
606
607 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ecb() {
608     return cipher_gost_grasshopper(EVP_CIPH_ECB_MODE, GRASSHOPPER_CIPHER_ECB);
609 }
610
611 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_cbc() {
612     return cipher_gost_grasshopper(EVP_CIPH_CBC_MODE, GRASSHOPPER_CIPHER_CBC);
613 }
614
615 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ofb() {
616     return cipher_gost_grasshopper(EVP_CIPH_OFB_MODE, GRASSHOPPER_CIPHER_OFB);
617 }
618
619 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_cfb() {
620     return cipher_gost_grasshopper(EVP_CIPH_CFB_MODE, GRASSHOPPER_CIPHER_CFB);
621 }
622
623 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ctr() {
624     return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE, GRASSHOPPER_CIPHER_CTR);
625 }
626
627 void cipher_gost_grasshopper_destroy(void)
628 {
629     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB]);
630     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_ECB] = NULL;
631     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC]);
632     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CBC] = NULL;
633     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB]);
634     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_OFB] = NULL;
635     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB]);
636     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CFB] = NULL;
637     EVP_CIPHER_meth_free(gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR]);
638     gost_grasshopper_ciphers[GRASSHOPPER_CIPHER_CTR] = NULL;
639 }
640 #if defined(__cplusplus)
641 }
642 #endif