]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
Build with -Werror
[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                 8,
101                 false
102         },
103 };
104
105 /* Set 256 bit  key into context */
106 GRASSHOPPER_INLINE void gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx* c, const uint8_t* k) {
107                 int i;
108     for (i = 0; i < 2; i++) {
109         grasshopper_copy128(&c->key.k.k[i], (const grasshopper_w128_t*) (k + i * 16));
110     }
111     grasshopper_set_encrypt_key(&c->encrypt_round_keys, &c->key);
112     grasshopper_set_decrypt_key(&c->decrypt_round_keys, &c->key);
113 }
114
115 /* Cleans up key from context */
116 GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx* c) {
117                 int i;
118     for (i = 0; i < 2; i++) {
119         grasshopper_zero128(&c->key.k.k[i]);
120     }
121     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
122         grasshopper_zero128(&c->encrypt_round_keys.k[i]);
123     }
124     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
125         grasshopper_zero128(&c->decrypt_round_keys.k[i]);
126     }
127     grasshopper_zero128(&c->buffer);
128 }
129
130 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ofb(gost_grasshopper_cipher_ctx* c) {
131     gost_grasshopper_cipher_ctx_ofb* ctx = (gost_grasshopper_cipher_ctx_ofb*) c;
132
133     grasshopper_zero128(&ctx->buffer1);
134 }
135
136 static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx* c) {
137     gost_grasshopper_cipher_ctx_ctr* ctx = (gost_grasshopper_cipher_ctx_ctr*) c;
138
139     grasshopper_zero128(&ctx->iv_buffer);
140     grasshopper_zero128(&ctx->partial_buffer);
141
142     ctx->counter = 0;
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
214     grasshopper_zero128(&c->iv_buffer);
215     grasshopper_zero128(&c->partial_buffer);
216
217     c->counter = 0;
218
219     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
220 }
221
222 GRASSHOPPER_INLINE int gost_grasshopper_cipher_do(EVP_CIPHER_CTX* ctx, unsigned char* out,
223                                                          const unsigned char* in, size_t inl) {
224     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
225     struct GRASSHOPPER_CIPHER_PARAMS* params = &gost_cipher_params[c->type];
226
227     return params->do_cipher(ctx, out, in, inl);
228 }
229
230 int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX* ctx, unsigned char* out,
231                                           const unsigned char* in, size_t inl) {
232     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
233     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
234     const unsigned char* current_in = in;
235     unsigned char* current_out = out;
236     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
237     size_t i;
238
239     for (i = 0; i < blocks; i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out += GRASSHOPPER_BLOCK_SIZE) {
240         if (encrypting) {
241             grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) current_in,
242                                       (grasshopper_w128_t*) current_out,
243                                       &c->buffer);
244         } else {
245             grasshopper_decrypt_block(&c->decrypt_round_keys, (grasshopper_w128_t*) current_in,
246                                       (grasshopper_w128_t*) current_out,
247                                       &c->buffer);
248         }
249     }
250
251     return 1;
252 }
253
254 int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX* ctx, unsigned char* out,
255                                           const unsigned char* in, size_t inl) {
256     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
257     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
258     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
259     const unsigned char* current_in = in;
260     unsigned char* current_out = out;
261     grasshopper_w128_t* currentInputBlock;
262     grasshopper_w128_t* currentOutputBlock;
263     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
264     size_t i;
265     grasshopper_w128_t* currentBlock;
266
267     currentBlock = (grasshopper_w128_t*) iv;
268
269     for (i = 0; i < blocks; i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out += GRASSHOPPER_BLOCK_SIZE) {
270         currentInputBlock = (grasshopper_w128_t*) current_in;
271         currentOutputBlock = (grasshopper_w128_t*) current_out;
272         if (encrypting) {
273             grasshopper_append128(currentBlock, currentInputBlock);
274             grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock, currentOutputBlock, &c->buffer);
275             grasshopper_copy128(currentBlock, currentOutputBlock);
276         } else {
277             grasshopper_decrypt_block(&c->decrypt_round_keys, currentInputBlock, currentOutputBlock, &c->buffer);
278             grasshopper_append128(currentOutputBlock, currentBlock);
279             grasshopper_copy128(currentBlock, currentInputBlock);
280         }
281     }
282
283     return 1;
284 }
285
286 int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out,
287                                           const unsigned char* in, size_t inl) {
288     gost_grasshopper_cipher_ctx_ctr* c = (gost_grasshopper_cipher_ctx_ctr*) EVP_CIPHER_CTX_get_cipher_data(ctx);
289     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
290     const unsigned char* current_in = in;
291     unsigned char* current_out = out;
292     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
293     grasshopper_w128_t* currentInputBlock;
294     grasshopper_w128_t* currentOutputBlock;
295     size_t lasted;
296     size_t i;
297
298     memcpy(&c->iv_buffer, iv, 8);
299
300     // full parts
301     for (i = 0; i < blocks; i++) {
302         currentInputBlock = (grasshopper_w128_t*) current_in;
303         currentOutputBlock = (grasshopper_w128_t*) current_out;
304         memcpy(c->iv_buffer.b + 8, &c->counter, 8);
305         grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, currentOutputBlock, &c->c.buffer);
306         grasshopper_append128(currentOutputBlock, currentInputBlock);
307         c->counter += 1;
308         current_in += GRASSHOPPER_BLOCK_SIZE;
309         current_out += GRASSHOPPER_BLOCK_SIZE;
310     }
311
312     // last part
313     lasted = inl - blocks * GRASSHOPPER_BLOCK_SIZE;
314     if (lasted > 0) {
315         currentInputBlock = (grasshopper_w128_t*) current_in;
316         currentOutputBlock = (grasshopper_w128_t*) current_out;
317         memcpy(c->iv_buffer.b + 8, &c->counter, 8);
318         grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, &c->partial_buffer, &c->c.buffer);
319         for (i = 0; i < lasted; i++) {
320             currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i];
321         }
322         c->counter += 1;
323     }
324
325     return 1;
326 }
327
328 static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx_ofb* ctx, grasshopper_w128_t* iv,
329                                       grasshopper_w128_t* buf) {
330     memcpy(&ctx->buffer1, iv, 16);
331     ctx->g = ctx->buffer1.b[0] | (ctx->buffer1.b[1] << 8) | (ctx->buffer1.b[2] << 16) |
332              ((uint32_t) ctx->buffer1.b[3] << 24);
333     ctx->g += 0x01010101;
334     ctx->buffer1.b[0] = (unsigned char) (ctx->g & 0xff);
335     ctx->buffer1.b[1] = (unsigned char) ((ctx->g >> 8) & 0xff);
336     ctx->buffer1.b[2] = (unsigned char) ((ctx->g >> 16) & 0xff);
337     ctx->buffer1.b[3] = (unsigned char) ((ctx->g >> 24) & 0xff);
338     ctx->g = ctx->buffer1.b[4] | (ctx->buffer1.b[5] << 8) | (ctx->buffer1.b[6] << 16) |
339              ((uint32_t) ctx->buffer1.b[7] << 24);
340     ctx->go = ctx->g;
341     ctx->g += 0x01010104;
342     if (ctx->go > ctx->g) {                 /* overflow */
343         ctx->g++;
344     }
345     ctx->buffer1.b[4] = (unsigned char) (ctx->g & 0xff);
346     ctx->buffer1.b[5] = (unsigned char) ((ctx->g >> 8) & 0xff);
347     ctx->buffer1.b[6] = (unsigned char) ((ctx->g >> 16) & 0xff);
348     ctx->buffer1.b[7] = (unsigned char) ((ctx->g >> 24) & 0xff);
349     ctx->g = ctx->buffer1.b[8] | (ctx->buffer1.b[9] << 8) | (ctx->buffer1.b[10] << 16) |
350              ((uint32_t) ctx->buffer1.b[11] << 24);
351     ctx->go = ctx->g;
352     ctx->g += 0x01010107;
353     if (ctx->go > ctx->g) {                 /* overflow */
354         ctx->g++;
355     }
356     ctx->buffer1.b[8] = (unsigned char) (ctx->g & 0xff);
357     ctx->buffer1.b[9] = (unsigned char) ((ctx->g >> 8) & 0xff);
358     ctx->buffer1.b[10] = (unsigned char) ((ctx->g >> 16) & 0xff);
359     ctx->buffer1.b[11] = (unsigned char) ((ctx->g >> 24) & 0xff);
360     ctx->g = ctx->buffer1.b[12] | (ctx->buffer1.b[13] << 8) | (ctx->buffer1.b[14] << 16) |
361              ((uint32_t) ctx->buffer1.b[15] << 24);
362     ctx->go = ctx->g;
363     ctx->g += 0x01010110;
364     if (ctx->go > ctx->g) {                 /* overflow */
365         ctx->g++;
366     }
367     ctx->buffer1.b[12] = (unsigned char) (ctx->g & 0xff);
368     ctx->buffer1.b[13] = (unsigned char) ((ctx->g >> 8) & 0xff);
369     ctx->buffer1.b[14] = (unsigned char) ((ctx->g >> 16) & 0xff);
370     ctx->buffer1.b[15] = (unsigned char) ((ctx->g >> 24) & 0xff);
371     memcpy(iv, &ctx->buffer1, 16);
372     grasshopper_encrypt_block(&ctx->c.encrypt_round_keys, &ctx->buffer1, buf, &ctx->c.buffer);
373 }
374
375 int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX* ctx, unsigned char* out,
376                                           const unsigned char* in, size_t inl) {
377     gost_grasshopper_cipher_ctx_ofb* c = (gost_grasshopper_cipher_ctx_ofb*) EVP_CIPHER_CTX_get_cipher_data(ctx);
378     const unsigned char* in_ptr = in;
379     unsigned char* out_ptr = out;
380     unsigned char* buf = EVP_CIPHER_CTX_buf_noconst(ctx);
381     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
382     int num = EVP_CIPHER_CTX_num(ctx);
383     size_t i = 0;
384     size_t j;
385
386     /* process partial block if any */
387     if (num > 0) {
388         for (j = (size_t) num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
389              j++, i++, in_ptr++, out_ptr++) {
390             *out_ptr = buf[j] ^ (*in_ptr);
391         }
392         if (j == GRASSHOPPER_BLOCK_SIZE) {
393             EVP_CIPHER_CTX_set_num(ctx, 0);
394         } else {
395             EVP_CIPHER_CTX_set_num(ctx, (int) j);
396             return 1;
397         }
398     }
399
400     for (; i + GRASSHOPPER_BLOCK_SIZE <
401            inl; i += GRASSHOPPER_BLOCK_SIZE, in_ptr += GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
402         /*
403          * block cipher current iv
404          */
405         /* Encrypt */
406         gost_grasshopper_cnt_next(c, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf);
407
408         /*
409          * xor next block of input text with it and output it
410          */
411         /*
412          * output this block
413          */
414         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
415             out_ptr[j] = buf[j] ^ in_ptr[j];
416         }
417     }
418
419     /* Process rest of buffer */
420     if (i < inl) {
421         gost_grasshopper_cnt_next(c, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf);
422         for (j = 0; i < inl; j++, i++) {
423             out_ptr[j] = buf[j] ^ in_ptr[j];
424         }
425         EVP_CIPHER_CTX_set_num(ctx, (int) j);
426     } else {
427         EVP_CIPHER_CTX_set_num(ctx, 0);
428     }
429
430     return 1;
431 }
432
433 int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX* ctx, unsigned char* out,
434                                           const unsigned char* in, size_t inl) {
435     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
436     const unsigned char* in_ptr = in;
437     unsigned char* out_ptr = out;
438     unsigned char* buf = EVP_CIPHER_CTX_buf_noconst(ctx);
439     unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx);
440     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
441     int num = EVP_CIPHER_CTX_num(ctx);
442     size_t i = 0;
443     size_t j = 0;
444
445     /* process partial block if any */
446     if (num > 0) {
447         for (j = (size_t) num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl; j++, i++, in_ptr++, out_ptr++) {
448             if (!encrypting) {
449                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
450             }
451             *out_ptr = buf[j] ^ (*in_ptr);
452             if (encrypting) {
453                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
454             }
455         }
456         if (j == GRASSHOPPER_BLOCK_SIZE) {
457             memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE);
458             EVP_CIPHER_CTX_set_num(ctx, 0);
459         } else {
460             EVP_CIPHER_CTX_set_num(ctx, (int) j);
461             return 1;
462         }
463     }
464
465     for (; i + GRASSHOPPER_BLOCK_SIZE <
466            inl; i += GRASSHOPPER_BLOCK_SIZE, in_ptr += GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
467         /*
468          * block cipher current iv
469          */
470         grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf,
471                                   &c->buffer);
472         /*
473          * xor next block of input text with it and output it
474          */
475         /*
476          * output this block
477          */
478         if (!encrypting) {
479             memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
480         }
481         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
482             out_ptr[j] = buf[j] ^ in_ptr[j];
483         }
484         /* Encrypt */
485         /* Next iv is next block of cipher text */
486         if (encrypting) {
487             memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
488         }
489     }
490
491     /* Process rest of buffer */
492     if (i < inl) {
493         grasshopper_encrypt_block(&c->encrypt_round_keys, (grasshopper_w128_t*) iv, (grasshopper_w128_t*) buf,
494                                   &c->buffer);
495         if (!encrypting) {
496             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
497         }
498         for (j = 0; i < inl; j++, i++) {
499             out_ptr[j] = buf[j] ^ in_ptr[j];
500         }
501         EVP_CIPHER_CTX_set_num(ctx, (int) j);
502         if (encrypting) {
503             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
504         }
505     } else {
506         EVP_CIPHER_CTX_set_num(ctx, 0);
507     }
508
509     return 1;
510 }
511
512 int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX* ctx) {
513     gost_grasshopper_cipher_ctx* c = (gost_grasshopper_cipher_ctx*) EVP_CIPHER_CTX_get_cipher_data(ctx);
514     struct GRASSHOPPER_CIPHER_PARAMS* params = &gost_cipher_params[c->type];
515
516     gost_grasshopper_cipher_destroy(c);
517     if (params->destroy_cipher != NULL) {
518         params->destroy_cipher(c);
519     }
520
521     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
522
523     return 1;
524 }
525
526 int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params) {
527     int len = 0;
528     unsigned char* buf = NULL;
529     unsigned char* p = NULL;
530     ASN1_OCTET_STRING* os = NULL;
531
532     os = ASN1_OCTET_STRING_new();
533
534     if (!os || !ASN1_OCTET_STRING_set(os, buf, len)) {
535         OPENSSL_free(buf);
536         GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE);
537         return 0;
538     }
539     OPENSSL_free(buf);
540
541     ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
542     return 1;
543 }
544
545 GRASSHOPPER_INLINE int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX* ctx, ASN1_TYPE* params) {
546     int ret = -1;
547
548     if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
549         return ret;
550     }
551
552     return 1;
553 }
554
555 int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX* ctx, int type, int arg, void* ptr) {
556     switch (type) {
557         case EVP_CTRL_RAND_KEY: {
558             if (RAND_bytes((unsigned char*) ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
559                 GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR);
560                 return -1;
561             }
562             break;
563         }
564         default:
565             GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
566             return -1;
567     }
568     return 1;
569 }
570
571 GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_create(int cipher_type, int block_size) {
572     return EVP_CIPHER_meth_new(cipher_type,
573                                block_size  /* block_size */,
574                                GRASSHOPPER_KEY_SIZE /* key_size */);
575 }
576
577 const int cipher_gost_grasshopper_setup(EVP_CIPHER* cipher, uint8_t mode, int iv_size, bool padding) {
578     return EVP_CIPHER_meth_set_iv_length(cipher, iv_size) &&
579            EVP_CIPHER_meth_set_flags(cipher, (unsigned long) (
580                    mode |
581                    ((!padding) ? EVP_CIPH_NO_PADDING : 0) |
582                    ((iv_size > 0) ? EVP_CIPH_CUSTOM_IV : 0) |
583                    EVP_CIPH_RAND_KEY |
584                    EVP_CIPH_ALWAYS_CALL_INIT)
585            ) &&
586            EVP_CIPHER_meth_set_cleanup(cipher, gost_grasshopper_cipher_cleanup) &&
587            EVP_CIPHER_meth_set_set_asn1_params(cipher, gost_grasshopper_set_asn1_parameters) &&
588            EVP_CIPHER_meth_set_get_asn1_params(cipher, gost_grasshopper_get_asn1_parameters) &&
589            EVP_CIPHER_meth_set_ctrl(cipher, gost_grasshopper_cipher_ctl) &&
590            EVP_CIPHER_meth_set_do_cipher(cipher, gost_grasshopper_cipher_do);
591 }
592
593 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper(uint8_t mode, uint8_t num) {
594     EVP_CIPHER** cipher;
595     struct GRASSHOPPER_CIPHER_PARAMS* params;
596
597     cipher = &gost_grasshopper_ciphers[num];
598
599     if (*cipher == NULL) {
600         params = &gost_cipher_params[num];
601
602         int nid = params->nid;
603         grasshopper_init_cipher_func init_cipher = params->init_cipher;
604         int block_size = params->block_size;
605         int ctx_size = params->ctx_size;
606         int iv_size = params->iv_size;
607         bool padding = params->padding;
608
609         *cipher = cipher_gost_grasshopper_create(nid, block_size);
610         if (*cipher == NULL) {
611             return NULL;
612         }
613
614         if (!cipher_gost_grasshopper_setup(*cipher, mode, iv_size, padding) ||
615             !EVP_CIPHER_meth_set_init(*cipher, init_cipher) ||
616             !EVP_CIPHER_meth_set_impl_ctx_size(*cipher, ctx_size)) {
617             EVP_CIPHER_meth_free(*cipher);
618             *cipher = NULL;
619         }
620     }
621
622     return *cipher;
623 }
624
625 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ecb() {
626     return cipher_gost_grasshopper(EVP_CIPH_ECB_MODE, GRASSHOPPER_CIPHER_ECB);
627 }
628
629 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_cbc() {
630     return cipher_gost_grasshopper(EVP_CIPH_CBC_MODE, GRASSHOPPER_CIPHER_CBC);
631 }
632
633 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ofb() {
634     return cipher_gost_grasshopper(EVP_CIPH_OFB_MODE, GRASSHOPPER_CIPHER_OFB);
635 }
636
637 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_cfb() {
638     return cipher_gost_grasshopper(EVP_CIPH_CFB_MODE, GRASSHOPPER_CIPHER_CFB);
639 }
640
641 const GRASSHOPPER_INLINE EVP_CIPHER* cipher_gost_grasshopper_ctr() {
642     return cipher_gost_grasshopper(EVP_CIPH_CTR_MODE, GRASSHOPPER_CIPHER_CTR);
643 }
644
645 #if defined(__cplusplus)
646 }
647 #endif