]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
Merge branch 'master' of https://github.com/gost-engine/engine
[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 GOST_cipher grasshopper_template_cipher = {
32     .block_size = GRASSHOPPER_BLOCK_SIZE,
33     .key_len = GRASSHOPPER_KEY_SIZE,
34     .flags = EVP_CIPH_RAND_KEY |
35         EVP_CIPH_ALWAYS_CALL_INIT,
36     .cleanup = gost_grasshopper_cipher_cleanup,
37     .ctx_size = sizeof(gost_grasshopper_cipher_ctx),
38     .set_asn1_parameters = gost_grasshopper_set_asn1_parameters,
39     .get_asn1_parameters = gost_grasshopper_get_asn1_parameters,
40     .ctrl = gost_grasshopper_cipher_ctl,
41 };
42
43 GOST_cipher grasshopper_ecb_cipher = {
44     .nid = NID_grasshopper_ecb,
45     .template = &grasshopper_template_cipher,
46     .flags = EVP_CIPH_ECB_MODE,
47     .init = gost_grasshopper_cipher_init_ecb,
48     .do_cipher = gost_grasshopper_cipher_do_ecb,
49 };
50
51 GOST_cipher grasshopper_cbc_cipher = {
52     .nid = NID_grasshopper_cbc,
53     .template = &grasshopper_template_cipher,
54     .iv_len = 16,
55     .flags = EVP_CIPH_CBC_MODE |
56         EVP_CIPH_CUSTOM_IV,
57     .init = gost_grasshopper_cipher_init_cbc,
58     .do_cipher = gost_grasshopper_cipher_do_cbc,
59 };
60
61 GOST_cipher grasshopper_ofb_cipher = {
62     .nid = NID_grasshopper_ofb,
63     .template = &grasshopper_template_cipher,
64     .block_size = 1,
65     .iv_len = 16,
66     .flags = EVP_CIPH_OFB_MODE |
67         EVP_CIPH_NO_PADDING |
68         EVP_CIPH_CUSTOM_IV,
69     .init = gost_grasshopper_cipher_init_ofb,
70     .do_cipher = gost_grasshopper_cipher_do_ofb,
71 };
72
73 GOST_cipher grasshopper_cfb_cipher = {
74     .nid = NID_grasshopper_cfb,
75     .template = &grasshopper_template_cipher,
76     .block_size = 1,
77     .iv_len = 16,
78     .flags = EVP_CIPH_CFB_MODE |
79         EVP_CIPH_NO_PADDING |
80         EVP_CIPH_CUSTOM_IV,
81     .init = gost_grasshopper_cipher_init_cfb,
82     .do_cipher = gost_grasshopper_cipher_do_cfb,
83 };
84
85 GOST_cipher grasshopper_ctr_cipher = {
86     .nid = NID_grasshopper_ctr,
87     .template = &grasshopper_template_cipher,
88     .block_size = 1,
89     .iv_len = 8,
90     .flags = EVP_CIPH_CTR_MODE |
91         EVP_CIPH_NO_PADDING |
92         EVP_CIPH_CUSTOM_IV,
93     .init = gost_grasshopper_cipher_init_ctr,
94     .do_cipher = gost_grasshopper_cipher_do_ctr,
95     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
96 };
97
98 GOST_cipher grasshopper_ctr_acpkm_cipher = {
99     .nid = NID_kuznyechik_ctr_acpkm,
100     .template = &grasshopper_template_cipher,
101     .block_size = 1,
102     .iv_len = 8,
103     .flags = EVP_CIPH_CTR_MODE |
104         EVP_CIPH_NO_PADDING |
105         EVP_CIPH_CUSTOM_IV,
106     .init = gost_grasshopper_cipher_init_ctracpkm,
107     .do_cipher = gost_grasshopper_cipher_do_ctracpkm,
108     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
109 };
110
111 GOST_cipher grasshopper_ctr_acpkm_omac_cipher = {
112     .nid = NID_kuznyechik_ctr_acpkm_omac,
113     .template = &grasshopper_template_cipher,
114     .block_size = 1,
115     .iv_len = 8,
116     .flags = EVP_CIPH_CTR_MODE |
117         EVP_CIPH_NO_PADDING |
118         EVP_CIPH_CUSTOM_IV |
119         EVP_CIPH_FLAG_CUSTOM_CIPHER |
120         EVP_CIPH_FLAG_CIPHER_WITH_MAC |
121         EVP_CIPH_CUSTOM_COPY,
122     .init = gost_grasshopper_cipher_init_ctracpkm_omac,
123     .do_cipher = gost_grasshopper_cipher_do_ctracpkm_omac,
124     .ctx_size = sizeof(gost_grasshopper_cipher_ctx_ctr),
125 };
126
127 /* first 256 bit of D from draft-irtf-cfrg-re-keying-12 */
128 static const unsigned char ACPKM_D_2018[] = {
129     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /*  64 bit */
130     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 128 bit */
131     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
132     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 256 bit */
133 };
134
135 static void acpkm_next(gost_grasshopper_cipher_ctx * c)
136 {
137     unsigned char newkey[GRASSHOPPER_KEY_SIZE];
138     const int J = GRASSHOPPER_KEY_SIZE / GRASSHOPPER_BLOCK_SIZE;
139     int n;
140
141     for (n = 0; n < J; n++) {
142         const unsigned char *D_n = &ACPKM_D_2018[n * GRASSHOPPER_BLOCK_SIZE];
143
144         grasshopper_encrypt_block(&c->encrypt_round_keys,
145                                   (grasshopper_w128_t *) D_n,
146                                   (grasshopper_w128_t *) & newkey[n *
147                                                                   GRASSHOPPER_BLOCK_SIZE],
148                                   &c->buffer);
149     }
150     gost_grasshopper_cipher_key(c, newkey);
151 }
152
153 /* Set 256 bit  key into context */
154 static GRASSHOPPER_INLINE void
155 gost_grasshopper_cipher_key(gost_grasshopper_cipher_ctx * c, const uint8_t *k)
156 {
157     int i;
158     for (i = 0; i < 2; i++) {
159         grasshopper_copy128(&c->key.k.k[i],
160                             (const grasshopper_w128_t *)(k + i * 16));
161     }
162
163     grasshopper_set_encrypt_key(&c->encrypt_round_keys, &c->key);
164     grasshopper_set_decrypt_key(&c->decrypt_round_keys, &c->key);
165 }
166
167 /* Set master 256-bit key to be used in TLSTREE calculation into context */
168 static GRASSHOPPER_INLINE void
169 gost_grasshopper_master_key(gost_grasshopper_cipher_ctx * c, const uint8_t *k)
170 {
171     int i;
172     for (i = 0; i < 2; i++) {
173         grasshopper_copy128(&c->master_key.k.k[i],
174                             (const grasshopper_w128_t *)(k + i * 16));
175     }
176 }
177
178 /* Cleans up key from context */
179 static GRASSHOPPER_INLINE void
180 gost_grasshopper_cipher_destroy(gost_grasshopper_cipher_ctx * c)
181 {
182     int i;
183     for (i = 0; i < 2; i++) {
184         grasshopper_zero128(&c->key.k.k[i]);
185         grasshopper_zero128(&c->master_key.k.k[i]);
186     }
187     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
188         grasshopper_zero128(&c->encrypt_round_keys.k[i]);
189     }
190     for (i = 0; i < GRASSHOPPER_ROUND_KEYS_COUNT; i++) {
191         grasshopper_zero128(&c->decrypt_round_keys.k[i]);
192     }
193     grasshopper_zero128(&c->buffer);
194 }
195
196 static GRASSHOPPER_INLINE void
197 gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx * c)
198 {
199     gost_grasshopper_cipher_ctx_ctr *ctx =
200         (gost_grasshopper_cipher_ctx_ctr *) c;
201
202     if (ctx->omac_ctx)
203         EVP_MD_CTX_free(ctx->omac_ctx);
204
205     grasshopper_zero128(&ctx->partial_buffer);
206 }
207
208 static int gost_grasshopper_cipher_init(EVP_CIPHER_CTX *ctx,
209                                  const unsigned char *key,
210                                  const unsigned char *iv, int enc)
211 {
212     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
213
214     if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) {
215         EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx));
216         if (enc && c->type == GRASSHOPPER_CIPHER_CTRACPKM) {
217             gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
218             if (init_zero_kdf_seed(ctr->kdf_seed) == 0)
219                 return -1;
220         }
221     }
222
223     if (key != NULL) {
224         gost_grasshopper_cipher_key(c, key);
225         gost_grasshopper_master_key(c, key);
226     }
227
228     if (iv != NULL) {
229         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv,
230                EVP_CIPHER_CTX_iv_length(ctx));
231     }
232
233     memcpy(EVP_CIPHER_CTX_iv_noconst(ctx),
234            EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx));
235
236     grasshopper_zero128(&c->buffer);
237
238     return 1;
239 }
240
241 static GRASSHOPPER_INLINE int
242 gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX *ctx, const unsigned char
243                                  *key, const unsigned char
244                                  *iv, int enc)
245 {
246     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
247     c->type = GRASSHOPPER_CIPHER_ECB;
248     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
249 }
250
251 static GRASSHOPPER_INLINE int
252 gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char
253                                  *key, const unsigned char
254                                  *iv, int enc)
255 {
256     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
257     c->type = GRASSHOPPER_CIPHER_CBC;
258     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
259 }
260
261 static GRASSHOPPER_INLINE
262 int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX *ctx, const unsigned char
263                                      *key, const unsigned char
264                                      *iv, int enc)
265 {
266     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
267     c->type = GRASSHOPPER_CIPHER_OFB;
268     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
269 }
270
271 static GRASSHOPPER_INLINE int
272 gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX *ctx, const unsigned char
273                                  *key, const unsigned char
274                                  *iv, int enc)
275 {
276     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
277     c->type = GRASSHOPPER_CIPHER_CFB;
278     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
279 }
280
281 static GRASSHOPPER_INLINE int
282 gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx, const unsigned char
283                                  *key, const unsigned char
284                                  *iv, int enc)
285 {
286     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
287
288     c->c.type = GRASSHOPPER_CIPHER_CTR;
289     EVP_CIPHER_CTX_set_num(ctx, 0);
290
291     grasshopper_zero128(&c->partial_buffer);
292
293     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
294 }
295
296 static GRASSHOPPER_INLINE int
297 gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX
298                                       *ctx, const unsigned
299                                       char *key, const unsigned
300                                       char *iv, int enc)
301 {
302     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
303
304     /* NB: setting type makes EVP do_cipher callback useless */
305     c->c.type = GRASSHOPPER_CIPHER_CTRACPKM;
306     EVP_CIPHER_CTX_set_num(ctx, 0);
307     c->section_size = 4096;
308
309     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
310 }
311
312 static GRASSHOPPER_INLINE int
313 gost_grasshopper_cipher_init_ctracpkm_omac(EVP_CIPHER_CTX
314                                            *ctx, const unsigned
315                                            char *key, const unsigned
316                                            char *iv, int enc)
317 {
318     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
319
320     /* NB: setting type makes EVP do_cipher callback useless */
321     c->c.type = GRASSHOPPER_CIPHER_CTRACPKMOMAC;
322     EVP_CIPHER_CTX_set_num(ctx, 0);
323     c->section_size = 4096;
324
325     if (key) {
326         unsigned char cipher_key[32];
327         c->omac_ctx = EVP_MD_CTX_new();
328
329         if (c->omac_ctx == NULL) {
330             GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC, ERR_R_MALLOC_FAILURE);
331             return 0;
332         }
333
334         if (gost2015_acpkm_omac_init(NID_kuznyechik_mac, enc, key,
335            c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
336             EVP_MD_CTX_free(c->omac_ctx);
337             c->omac_ctx = NULL;
338             return 0;
339         }
340
341         return gost_grasshopper_cipher_init(ctx, cipher_key, iv, enc);
342     }
343
344     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
345 }
346
347 static int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
348                                           const unsigned char *in, size_t inl)
349 {
350     gost_grasshopper_cipher_ctx *c =
351         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
352     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
353     const unsigned char *current_in = in;
354     unsigned char *current_out = out;
355     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
356     size_t i;
357
358     for (i = 0; i < blocks;
359          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
360          GRASSHOPPER_BLOCK_SIZE) {
361         if (encrypting) {
362             grasshopper_encrypt_block(&c->encrypt_round_keys,
363                                       (grasshopper_w128_t *) current_in,
364                                       (grasshopper_w128_t *) current_out,
365                                       &c->buffer);
366         } else {
367             grasshopper_decrypt_block(&c->decrypt_round_keys,
368                                       (grasshopper_w128_t *) current_in,
369                                       (grasshopper_w128_t *) current_out,
370                                       &c->buffer);
371         }
372     }
373
374     return 1;
375 }
376
377 static int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
378                                           const unsigned char *in, size_t inl)
379 {
380     gost_grasshopper_cipher_ctx *c =
381         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
382     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
383     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
384     const unsigned char *current_in = in;
385     unsigned char *current_out = out;
386     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
387     size_t i;
388     grasshopper_w128_t *currentBlock;
389
390     currentBlock = (grasshopper_w128_t *) iv;
391
392     for (i = 0; i < blocks;
393          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
394          GRASSHOPPER_BLOCK_SIZE) {
395         grasshopper_w128_t *currentInputBlock = (grasshopper_w128_t *) current_in;
396         grasshopper_w128_t *currentOutputBlock = (grasshopper_w128_t *) current_out;
397         if (encrypting) {
398             grasshopper_append128(currentBlock, currentInputBlock);
399             grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock,
400                                       currentOutputBlock, &c->buffer);
401             grasshopper_copy128(currentBlock, currentOutputBlock);
402         } else {
403             grasshopper_w128_t tmp;
404
405             grasshopper_copy128(&tmp, currentInputBlock);
406             grasshopper_decrypt_block(&c->decrypt_round_keys,
407                                       currentInputBlock, currentOutputBlock,
408                                       &c->buffer);
409             grasshopper_append128(currentOutputBlock, currentBlock);
410             grasshopper_copy128(currentBlock, &tmp);
411         }
412     }
413
414     return 1;
415 }
416
417 void inc_counter(unsigned char *counter, size_t counter_bytes)
418 {
419     unsigned int n = counter_bytes;
420
421     do {
422         unsigned char c;
423         --n;
424         c = counter[n];
425         ++c;
426         counter[n] = c;
427         if (c)
428             return;
429     } while (n);
430 }
431
432 /* increment counter (128-bit int) by 1 */
433 static void ctr128_inc(unsigned char *counter)
434 {
435     inc_counter(counter, 16);
436 }
437
438 static int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
439                                           const unsigned char *in, size_t inl)
440 {
441     gost_grasshopper_cipher_ctx_ctr *c = (gost_grasshopper_cipher_ctx_ctr *)
442         EVP_CIPHER_CTX_get_cipher_data(ctx);
443     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
444     const unsigned char *current_in = in;
445     unsigned char *current_out = out;
446     grasshopper_w128_t *currentInputBlock;
447     grasshopper_w128_t *currentOutputBlock;
448     unsigned int n = EVP_CIPHER_CTX_num(ctx);
449     size_t lasted = inl;
450     size_t i;
451     size_t blocks;
452     grasshopper_w128_t *iv_buffer;
453     grasshopper_w128_t tmp;
454
455     while (n && lasted) {
456         *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n];
457         --lasted;
458         n = (n + 1) % GRASSHOPPER_BLOCK_SIZE;
459     }
460     EVP_CIPHER_CTX_set_num(ctx, n);
461     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
462
463     iv_buffer = (grasshopper_w128_t *) iv;
464
465     // full parts
466     for (i = 0; i < blocks; i++) {
467         currentInputBlock = (grasshopper_w128_t *) current_in;
468         currentOutputBlock = (grasshopper_w128_t *) current_out;
469         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
470                                   &c->partial_buffer, &c->c.buffer);
471         grasshopper_plus128(&tmp, &c->partial_buffer, currentInputBlock);
472         grasshopper_copy128(currentOutputBlock, &tmp);
473         ctr128_inc(iv_buffer->b);
474         current_in += GRASSHOPPER_BLOCK_SIZE;
475         current_out += GRASSHOPPER_BLOCK_SIZE;
476         lasted -= GRASSHOPPER_BLOCK_SIZE;
477     }
478
479     if (lasted > 0) {
480         currentInputBlock = (grasshopper_w128_t *) current_in;
481         currentOutputBlock = (grasshopper_w128_t *) current_out;
482         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
483                                   &c->partial_buffer, &c->c.buffer);
484         for (i = 0; i < lasted; i++) {
485             currentOutputBlock->b[i] =
486                 c->partial_buffer.b[i] ^ currentInputBlock->b[i];
487         }
488         EVP_CIPHER_CTX_set_num(ctx, i);
489         ctr128_inc(iv_buffer->b);
490     }
491
492     return inl;
493 }
494
495 #define GRASSHOPPER_BLOCK_MASK (GRASSHOPPER_BLOCK_SIZE - 1)
496 static inline void apply_acpkm_grasshopper(gost_grasshopper_cipher_ctx_ctr *
497                                            ctx, unsigned int *num)
498 {
499     if (!ctx->section_size || (*num < ctx->section_size))
500         return;
501     acpkm_next(&ctx->c);
502     *num &= GRASSHOPPER_BLOCK_MASK;
503 }
504
505 /* If meshing is not configured via ctrl (setting section_size)
506  * this function works exactly like plain ctr */
507 static int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx,
508                                                unsigned char *out,
509                                                const unsigned char *in,
510                                                size_t inl)
511 {
512     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
513     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
514     unsigned int num = EVP_CIPHER_CTX_num(ctx);
515     size_t blocks, i, lasted = inl;
516     grasshopper_w128_t tmp;
517
518     while ((num & GRASSHOPPER_BLOCK_MASK) && lasted) {
519         *out++ = *in++ ^ c->partial_buffer.b[num & GRASSHOPPER_BLOCK_MASK];
520         --lasted;
521         num++;
522     }
523     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
524
525     // full parts
526     for (i = 0; i < blocks; i++) {
527         apply_acpkm_grasshopper(c, &num);
528         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
529                                   (grasshopper_w128_t *) iv,
530                                   (grasshopper_w128_t *) & c->partial_buffer,
531                                   &c->c.buffer);
532         grasshopper_plus128(&tmp, &c->partial_buffer,
533                             (grasshopper_w128_t *) in);
534         grasshopper_copy128((grasshopper_w128_t *) out, &tmp);
535         ctr128_inc(iv);
536         in += GRASSHOPPER_BLOCK_SIZE;
537         out += GRASSHOPPER_BLOCK_SIZE;
538         num += GRASSHOPPER_BLOCK_SIZE;
539         lasted -= GRASSHOPPER_BLOCK_SIZE;
540     }
541
542     // last part
543     if (lasted > 0) {
544         apply_acpkm_grasshopper(c, &num);
545         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
546                                   (grasshopper_w128_t *) iv,
547                                   &c->partial_buffer, &c->c.buffer);
548         for (i = 0; i < lasted; i++)
549             out[i] = c->partial_buffer.b[i] ^ in[i];
550         ctr128_inc(iv);
551         num += lasted;
552     }
553     EVP_CIPHER_CTX_set_num(ctx, num);
554
555     return inl;
556 }
557
558 static int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx,
559                                                     unsigned char *out,
560                                                     const unsigned char *in,
561                                                     size_t inl)
562 {
563     int result;
564     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
565     /* As in and out can be the same pointer, process unencrypted here */
566     if (EVP_CIPHER_CTX_encrypting(ctx))
567         EVP_DigestSignUpdate(c->omac_ctx, in, inl);
568
569     if (in == NULL && inl == 0) { /* Final call */
570         return gost2015_final_call(ctx, c->omac_ctx, KUZNYECHIK_MAC_MAX_SIZE, c->tag, gost_grasshopper_cipher_do_ctracpkm);
571     }
572
573     if (in == NULL) {
574         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_DO_CTRACPKM_OMAC, ERR_R_EVP_LIB);
575         return -1;
576     }
577     result = gost_grasshopper_cipher_do_ctracpkm(ctx, out, in, inl);
578
579     /* As in and out can be the same pointer, process decrypted here */
580     if (!EVP_CIPHER_CTX_encrypting(ctx))
581         EVP_DigestSignUpdate(c->omac_ctx, out, inl);
582
583     return result;
584 }
585 /*
586  * Fixed 128-bit IV implementation make shift regiser redundant.
587  */
588 static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx * ctx,
589                                       grasshopper_w128_t * iv,
590                                       grasshopper_w128_t * buf)
591 {
592     grasshopper_w128_t tmp;
593     memcpy(&tmp, iv, 16);
594     grasshopper_encrypt_block(&ctx->encrypt_round_keys, &tmp,
595                               buf, &ctx->buffer);
596     memcpy(iv, buf, 16);
597 }
598
599 static int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out,
600                                           const unsigned char *in, size_t inl)
601 {
602     gost_grasshopper_cipher_ctx *c = (gost_grasshopper_cipher_ctx *)
603         EVP_CIPHER_CTX_get_cipher_data(ctx);
604     const unsigned char *in_ptr = in;
605     unsigned char *out_ptr = out;
606     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
607     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
608     int num = EVP_CIPHER_CTX_num(ctx);
609     size_t i = 0;
610     size_t j;
611
612     /* process partial block if any */
613     if (num > 0) {
614         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
615              j++, i++, in_ptr++, out_ptr++) {
616             *out_ptr = buf[j] ^ (*in_ptr);
617         }
618         if (j == GRASSHOPPER_BLOCK_SIZE) {
619             EVP_CIPHER_CTX_set_num(ctx, 0);
620         } else {
621             EVP_CIPHER_CTX_set_num(ctx, (int)j);
622             return 1;
623         }
624     }
625
626     for (; i + GRASSHOPPER_BLOCK_SIZE <
627          inl;
628          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
629          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
630         /*
631          * block cipher current iv
632          */
633         /* Encrypt */
634         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
635                                   (grasshopper_w128_t *) buf);
636
637         /*
638          * xor next block of input text with it and output it
639          */
640         /*
641          * output this block
642          */
643         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
644             out_ptr[j] = buf[j] ^ in_ptr[j];
645         }
646     }
647
648     /* Process rest of buffer */
649     if (i < inl) {
650         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
651                                   (grasshopper_w128_t *) buf);
652         for (j = 0; i < inl; j++, i++) {
653             out_ptr[j] = buf[j] ^ in_ptr[j];
654         }
655         EVP_CIPHER_CTX_set_num(ctx, (int)j);
656     } else {
657         EVP_CIPHER_CTX_set_num(ctx, 0);
658     }
659
660     return 1;
661 }
662
663 static int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
664                                           const unsigned char *in, size_t inl)
665 {
666     gost_grasshopper_cipher_ctx *c =
667         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
668     const unsigned char *in_ptr = in;
669     unsigned char *out_ptr = out;
670     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
671     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
672     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
673     int num = EVP_CIPHER_CTX_num(ctx);
674     size_t i = 0;
675     size_t j = 0;
676
677     /* process partial block if any */
678     if (num > 0) {
679         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
680              j++, i++, in_ptr++, out_ptr++) {
681             if (!encrypting) {
682                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
683             }
684             *out_ptr = buf[j] ^ (*in_ptr);
685             if (encrypting) {
686                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
687             }
688         }
689         if (j == GRASSHOPPER_BLOCK_SIZE) {
690             memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE);
691             EVP_CIPHER_CTX_set_num(ctx, 0);
692         } else {
693             EVP_CIPHER_CTX_set_num(ctx, (int)j);
694             return 1;
695         }
696     }
697
698     for (; i + GRASSHOPPER_BLOCK_SIZE <
699          inl;
700          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
701          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
702         /*
703          * block cipher current iv
704          */
705         grasshopper_encrypt_block(&c->encrypt_round_keys,
706                                   (grasshopper_w128_t *) iv,
707                                   (grasshopper_w128_t *) buf, &c->buffer);
708         /*
709          * xor next block of input text with it and output it
710          */
711         /*
712          * output this block
713          */
714         if (!encrypting) {
715             memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
716         }
717         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
718             out_ptr[j] = buf[j] ^ in_ptr[j];
719         }
720         /* Encrypt */
721         /* Next iv is next block of cipher text */
722         if (encrypting) {
723             memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
724         }
725     }
726
727     /* Process rest of buffer */
728     if (i < inl) {
729         grasshopper_encrypt_block(&c->encrypt_round_keys,
730                                   (grasshopper_w128_t *) iv,
731                                   (grasshopper_w128_t *) buf, &c->buffer);
732         if (!encrypting) {
733             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
734         }
735         for (j = 0; i < inl; j++, i++) {
736             out_ptr[j] = buf[j] ^ in_ptr[j];
737         }
738         EVP_CIPHER_CTX_set_num(ctx, (int)j);
739         if (encrypting) {
740             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
741         }
742     } else {
743         EVP_CIPHER_CTX_set_num(ctx, 0);
744     }
745
746     return 1;
747 }
748
749 static int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX *ctx)
750 {
751     gost_grasshopper_cipher_ctx *c =
752         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
753
754     if (!c)
755         return 1;
756
757     if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE)
758         gost_grasshopper_cipher_destroy_ctr(c);
759
760     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
761
762     return 1;
763 }
764
765 static int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
766 {
767     if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
768         gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
769
770         /* CMS implies 256kb section_size */
771         ctr->section_size = 256*1024;
772
773         return gost2015_set_asn1_params(params,
774                EVP_CIPHER_CTX_original_iv(ctx), 8, ctr->kdf_seed);
775     }
776     return 0;
777 }
778
779 static GRASSHOPPER_INLINE int
780 gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
781 {
782     if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
783         gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
784
785         int iv_len = 16;
786         unsigned char iv[16];
787
788         if (gost2015_get_asn1_params(params, 16, iv, 8, ctr->kdf_seed) == 0) {
789             return 0;
790         }
791
792         memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, iv_len);
793         memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, iv_len);
794
795         /* CMS implies 256kb section_size */
796         ctr->section_size = 256*1024;
797         return 1;
798     }
799     return 0;
800 }
801
802 static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
803 {
804     switch (type) {
805     case EVP_CTRL_RAND_KEY:{
806             if (RAND_priv_bytes
807                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
808                 GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, GOST_R_RNG_ERROR);
809                 return -1;
810             }
811             break;
812         }
813     case EVP_CTRL_KEY_MESH:{
814             gost_grasshopper_cipher_ctx_ctr *c =
815                 EVP_CIPHER_CTX_get_cipher_data(ctx);
816             if ((c->c.type != GRASSHOPPER_CIPHER_CTRACPKM &&
817                 c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
818                 || (arg == 0)
819                || (arg % GRASSHOPPER_BLOCK_SIZE))
820                 return -1;
821             c->section_size = arg;
822             break;
823         }
824 #ifdef EVP_CTRL_TLS1_2_TLSTREE
825     case EVP_CTRL_TLS1_2_TLSTREE:
826         {
827           unsigned char newkey[32];
828           int mode = EVP_CIPHER_CTX_mode(ctx);
829           static const unsigned char zeroseq[8];
830           gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL;
831           gost_grasshopper_cipher_ctx *c = NULL;
832
833           unsigned char adjusted_iv[16];
834           unsigned char seq[8];
835           int j, carry;
836           if (mode != EVP_CIPH_CTR_MODE)
837             return -1;
838
839           ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *)
840             EVP_CIPHER_CTX_get_cipher_data(ctx);
841           c = &(ctr_ctx->c);
842
843           memcpy(seq, ptr, 8);
844           if (EVP_CIPHER_CTX_encrypting(ctx)) {
845             /*
846              * OpenSSL increments seq after mac calculation.
847              * As we have Mac-Then-Encrypt, we need decrement it here on encryption
848              * to derive the key correctly.
849              * */
850             if (memcmp(seq, zeroseq, 8) != 0)
851             {
852               for(j=7; j>=0; j--)
853               {
854                 if (seq[j] != 0) {seq[j]--; break;}
855                 else seq[j]  = 0xFF;
856               }
857             }
858           }
859           if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey,
860                 (const unsigned char *)seq) > 0) {
861             memset(adjusted_iv, 0, 16);
862             memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8);
863             for(j=7,carry=0; j>=0; j--)
864             {
865               int adj_byte = adjusted_iv[j]+seq[j]+carry;
866               carry = (adj_byte > 255) ? 1 : 0;
867               adjusted_iv[j] = adj_byte & 0xFF;
868             }
869             EVP_CIPHER_CTX_set_num(ctx, 0);
870             memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 16);
871
872             gost_grasshopper_cipher_key(c, newkey);
873             return 1;
874           }
875         }
876         return -1;
877 #endif
878 #if 0
879     case EVP_CTRL_AEAD_GET_TAG:
880     case EVP_CTRL_AEAD_SET_TAG:
881         {
882             int taglen = arg;
883             unsigned char *tag = ptr;
884
885             gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
886             if (c->c.type != GRASSHOPPER_CIPHER_MGM)
887                 return -1;
888
889             if (taglen > KUZNYECHIK_MAC_MAX_SIZE) {
890                 CRYPTOCOMerr(CRYPTOCOM_F_GOST_GRASSHOPPER_CIPHER_CTL,
891                         CRYPTOCOM_R_INVALID_TAG_LENGTH);
892                 return -1;
893             }
894
895             if (type == EVP_CTRL_AEAD_GET_TAG)
896                 memcpy(tag, c->final_tag, taglen);
897             else
898                 memcpy(c->final_tag, tag, taglen);
899
900             return 1;
901         }
902 #endif
903     case EVP_CTRL_PROCESS_UNPROTECTED:
904     {
905       STACK_OF(X509_ATTRIBUTE) *x = ptr;
906       gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
907
908       if (c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
909         return -1;
910
911       return gost2015_process_unprotected_attributes(x, arg, KUZNYECHIK_MAC_MAX_SIZE, c->tag);
912     }
913     return 1;
914     case EVP_CTRL_COPY: {
915         EVP_CIPHER_CTX *out = ptr;
916
917         gost_grasshopper_cipher_ctx_ctr *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out);
918         gost_grasshopper_cipher_ctx_ctr *in_cctx  = EVP_CIPHER_CTX_get_cipher_data(ctx);
919
920         if (in_cctx->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
921             return -1;
922
923         if (in_cctx->omac_ctx == out_cctx->omac_ctx) {
924             out_cctx->omac_ctx = EVP_MD_CTX_new();
925             if (out_cctx->omac_ctx == NULL) {
926                 GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, ERR_R_MALLOC_FAILURE);
927                 return -1;
928             }
929         }
930         return EVP_MD_CTX_copy(out_cctx->omac_ctx, in_cctx->omac_ctx);
931     }
932     default:
933         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL,
934                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
935         return -1;
936     }
937     return 1;
938 }
939
940 /* Called directly by CMAC_ACPKM_Init() */
941 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctracpkm()
942 {
943     return GOST_init_cipher(&grasshopper_ctr_acpkm_cipher);
944 }
945 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */