]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_grasshopper_cipher.c
gost_grasshopper_cipher: Remove redundant code
[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 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 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 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 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 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ecb(EVP_CIPHER_CTX *ctx, const unsigned char
242                                                         *key, const unsigned char
243                                                         *iv, int enc)
244 {
245     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
246     c->type = GRASSHOPPER_CIPHER_ECB;
247     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
248 }
249
250 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char
251                                                         *key, const unsigned char
252                                                         *iv, int enc)
253 {
254     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
255     c->type = GRASSHOPPER_CIPHER_CBC;
256     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
257 }
258
259 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ofb(EVP_CIPHER_CTX *ctx, const unsigned char
260                                                         *key, const unsigned char
261                                                         *iv, int enc)
262 {
263     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
264     c->type = GRASSHOPPER_CIPHER_OFB;
265     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
266 }
267
268 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_cfb(EVP_CIPHER_CTX *ctx, const unsigned char
269                                                         *key, const unsigned char
270                                                         *iv, int enc)
271 {
272     gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
273     c->type = GRASSHOPPER_CIPHER_CFB;
274     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
275 }
276
277 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX *ctx, const unsigned char
278                                                         *key, const unsigned char
279                                                         *iv, int enc)
280 {
281     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
282
283     c->c.type = GRASSHOPPER_CIPHER_CTR;
284     EVP_CIPHER_CTX_set_num(ctx, 0);
285
286     grasshopper_zero128(&c->partial_buffer);
287
288     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
289 }
290
291 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctracpkm(EVP_CIPHER_CTX
292                                                              *ctx, const unsigned
293                                                              char *key, const unsigned
294                                                              char *iv, int enc)
295 {
296     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
297
298     /* NB: setting type makes EVP do_cipher callback useless */
299     c->c.type = GRASSHOPPER_CIPHER_CTRACPKM;
300     EVP_CIPHER_CTX_set_num(ctx, 0);
301     c->section_size = 4096;
302
303     return gost_grasshopper_cipher_init(ctx, key, iv, enc);
304 }
305
306 GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctracpkm_omac(EVP_CIPHER_CTX
307                                                              *ctx, const unsigned
308                                                              char *key, const unsigned
309                                                              char *iv, int enc)
310 {
311         gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
312
313         /* NB: setting type makes EVP do_cipher callback useless */
314         c->c.type = GRASSHOPPER_CIPHER_CTRACPKMOMAC;
315         EVP_CIPHER_CTX_set_num(ctx, 0);
316         c->section_size = 4096;
317
318         if (key) {
319                 unsigned char cipher_key[32];
320                 c->omac_ctx = EVP_MD_CTX_new();
321
322                 if (c->omac_ctx == NULL) {
323                     GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_INIT_CTRACPKM_OMAC, ERR_R_MALLOC_FAILURE);
324                                 return 0;
325                 }
326
327                 if (gost2015_acpkm_omac_init(NID_kuznyechik_mac, enc, key,
328                                  c->omac_ctx, cipher_key, c->kdf_seed) != 1) {
329                     EVP_MD_CTX_free(c->omac_ctx);
330                                 c->omac_ctx = NULL;
331                     return 0;
332                 }
333
334                 return gost_grasshopper_cipher_init(ctx, cipher_key, iv, enc);
335         }
336
337         return gost_grasshopper_cipher_init(ctx, key, iv, enc);
338 }
339
340 int gost_grasshopper_cipher_do_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
341                                    const unsigned char *in, size_t inl)
342 {
343     gost_grasshopper_cipher_ctx *c =
344         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
345     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
346     const unsigned char *current_in = in;
347     unsigned char *current_out = out;
348     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
349     size_t i;
350
351     for (i = 0; i < blocks;
352          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
353          GRASSHOPPER_BLOCK_SIZE) {
354         if (encrypting) {
355             grasshopper_encrypt_block(&c->encrypt_round_keys,
356                                       (grasshopper_w128_t *) current_in,
357                                       (grasshopper_w128_t *) current_out,
358                                       &c->buffer);
359         } else {
360             grasshopper_decrypt_block(&c->decrypt_round_keys,
361                                       (grasshopper_w128_t *) current_in,
362                                       (grasshopper_w128_t *) current_out,
363                                       &c->buffer);
364         }
365     }
366
367     return 1;
368 }
369
370 int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
371                                    const unsigned char *in, size_t inl)
372 {
373     gost_grasshopper_cipher_ctx *c =
374         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
375     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
376     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
377     const unsigned char *current_in = in;
378     unsigned char *current_out = out;
379     size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE;
380     size_t i;
381     grasshopper_w128_t *currentBlock;
382
383     currentBlock = (grasshopper_w128_t *) iv;
384
385     for (i = 0; i < blocks;
386          i++, current_in += GRASSHOPPER_BLOCK_SIZE, current_out +=
387          GRASSHOPPER_BLOCK_SIZE) {
388         grasshopper_w128_t *currentInputBlock = (grasshopper_w128_t *) current_in;
389         grasshopper_w128_t *currentOutputBlock = (grasshopper_w128_t *) current_out;
390         if (encrypting) {
391             grasshopper_append128(currentBlock, currentInputBlock);
392             grasshopper_encrypt_block(&c->encrypt_round_keys, currentBlock,
393                                       currentOutputBlock, &c->buffer);
394             grasshopper_copy128(currentBlock, currentOutputBlock);
395         } else {
396             grasshopper_w128_t tmp;
397
398             grasshopper_copy128(&tmp, currentInputBlock);
399             grasshopper_decrypt_block(&c->decrypt_round_keys,
400                                       currentInputBlock, currentOutputBlock,
401                                       &c->buffer);
402             grasshopper_append128(currentOutputBlock, currentBlock);
403             grasshopper_copy128(currentBlock, &tmp);
404         }
405     }
406
407     return 1;
408 }
409
410 void inc_counter(unsigned char *counter, size_t counter_bytes)
411 {
412     unsigned int n = counter_bytes;
413
414     do {
415         unsigned char c;
416         --n;
417         c = counter[n];
418         ++c;
419         counter[n] = c;
420         if (c)
421             return;
422     } while (n);
423 }
424
425 /* increment counter (128-bit int) by 1 */
426 static void ctr128_inc(unsigned char *counter)
427 {
428     inc_counter(counter, 16);
429 }
430
431 int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
432                                    const unsigned char *in, size_t inl)
433 {
434     gost_grasshopper_cipher_ctx_ctr *c = (gost_grasshopper_cipher_ctx_ctr *)
435         EVP_CIPHER_CTX_get_cipher_data(ctx);
436     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
437     const unsigned char *current_in = in;
438     unsigned char *current_out = out;
439     grasshopper_w128_t *currentInputBlock;
440     grasshopper_w128_t *currentOutputBlock;
441     unsigned int n = EVP_CIPHER_CTX_num(ctx);
442     size_t lasted = inl;
443     size_t i;
444     size_t blocks;
445     grasshopper_w128_t *iv_buffer;
446     grasshopper_w128_t tmp;
447
448     while (n && lasted) {
449         *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n];
450         --lasted;
451         n = (n + 1) % GRASSHOPPER_BLOCK_SIZE;
452     }
453     EVP_CIPHER_CTX_set_num(ctx, n);
454     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
455
456     iv_buffer = (grasshopper_w128_t *) iv;
457
458     // full parts
459     for (i = 0; i < blocks; i++) {
460         currentInputBlock = (grasshopper_w128_t *) current_in;
461         currentOutputBlock = (grasshopper_w128_t *) current_out;
462         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
463                                   &c->partial_buffer, &c->c.buffer);
464         grasshopper_plus128(&tmp, &c->partial_buffer, currentInputBlock);
465         grasshopper_copy128(currentOutputBlock, &tmp);
466         ctr128_inc(iv_buffer->b);
467         current_in += GRASSHOPPER_BLOCK_SIZE;
468         current_out += GRASSHOPPER_BLOCK_SIZE;
469                                 lasted -= GRASSHOPPER_BLOCK_SIZE;
470     }
471
472     if (lasted > 0) {
473         currentInputBlock = (grasshopper_w128_t *) current_in;
474         currentOutputBlock = (grasshopper_w128_t *) current_out;
475         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
476                                   &c->partial_buffer, &c->c.buffer);
477         for (i = 0; i < lasted; i++) {
478             currentOutputBlock->b[i] =
479                 c->partial_buffer.b[i] ^ currentInputBlock->b[i];
480         }
481         EVP_CIPHER_CTX_set_num(ctx, i);
482         ctr128_inc(iv_buffer->b);
483     }
484
485     return inl;
486 }
487
488 #define GRASSHOPPER_BLOCK_MASK (GRASSHOPPER_BLOCK_SIZE - 1)
489 static inline void apply_acpkm_grasshopper(gost_grasshopper_cipher_ctx_ctr *
490                                            ctx, unsigned int *num)
491 {
492     if (!ctx->section_size || (*num < ctx->section_size))
493         return;
494     acpkm_next(&ctx->c);
495     *num &= GRASSHOPPER_BLOCK_MASK;
496 }
497
498 /* If meshing is not configured via ctrl (setting section_size)
499  * this function works exactly like plain ctr */
500 int gost_grasshopper_cipher_do_ctracpkm(EVP_CIPHER_CTX *ctx,
501                                         unsigned char *out,
502                                         const unsigned char *in, size_t inl)
503 {
504     gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
505     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
506     unsigned int num = EVP_CIPHER_CTX_num(ctx);
507     size_t blocks, i, lasted = inl;
508     grasshopper_w128_t tmp;
509
510     while ((num & GRASSHOPPER_BLOCK_MASK) && lasted) {
511         *out++ = *in++ ^ c->partial_buffer.b[num & GRASSHOPPER_BLOCK_MASK];
512         --lasted;
513         num++;
514     }
515     blocks = lasted / GRASSHOPPER_BLOCK_SIZE;
516
517     // full parts
518     for (i = 0; i < blocks; i++) {
519         apply_acpkm_grasshopper(c, &num);
520         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
521                                   (grasshopper_w128_t *) iv,
522                                   (grasshopper_w128_t *) & c->partial_buffer,
523                                   &c->c.buffer);
524         grasshopper_plus128(&tmp, &c->partial_buffer,
525                             (grasshopper_w128_t *) in);
526         grasshopper_copy128((grasshopper_w128_t *) out, &tmp);
527         ctr128_inc(iv);
528         in += GRASSHOPPER_BLOCK_SIZE;
529         out += GRASSHOPPER_BLOCK_SIZE;
530         num += GRASSHOPPER_BLOCK_SIZE;
531                                 lasted -= GRASSHOPPER_BLOCK_SIZE;
532     }
533
534     // last part
535     if (lasted > 0) {
536         apply_acpkm_grasshopper(c, &num);
537         grasshopper_encrypt_block(&c->c.encrypt_round_keys,
538                                   (grasshopper_w128_t *) iv,
539                                   &c->partial_buffer, &c->c.buffer);
540         for (i = 0; i < lasted; i++)
541             out[i] = c->partial_buffer.b[i] ^ in[i];
542         ctr128_inc(iv);
543         num += lasted;
544     }
545     EVP_CIPHER_CTX_set_num(ctx, num);
546
547     return inl;
548 }
549
550 int gost_grasshopper_cipher_do_ctracpkm_omac(EVP_CIPHER_CTX *ctx,
551                                         unsigned char *out,
552                                         const unsigned char *in, size_t inl)
553 {
554         int result;
555   gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
556         /* As in and out can be the same pointer, process unencrypted here */
557         if (EVP_CIPHER_CTX_encrypting(ctx))
558                 EVP_DigestSignUpdate(c->omac_ctx, in, inl);
559
560         if (in == NULL && inl == 0) { /* Final call */
561                 return gost2015_final_call(ctx, c->omac_ctx, KUZNYECHIK_MAC_MAX_SIZE, c->tag, gost_grasshopper_cipher_do_ctracpkm);
562         }
563
564   if (in == NULL) {
565       GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_DO_CTRACPKM_OMAC, ERR_R_EVP_LIB);
566       return -1;
567   }
568         result = gost_grasshopper_cipher_do_ctracpkm(ctx, out, in, inl);
569
570         /* As in and out can be the same pointer, process decrypted here */
571         if (!EVP_CIPHER_CTX_encrypting(ctx))
572                 EVP_DigestSignUpdate(c->omac_ctx, out, inl);
573
574         return result;
575 }
576 /*
577  * Fixed 128-bit IV implementation make shift regiser redundant.
578  */
579 static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx * ctx,
580                                       grasshopper_w128_t * iv,
581                                       grasshopper_w128_t * buf)
582 {
583     grasshopper_w128_t tmp;
584     memcpy(&tmp, iv, 16);
585     grasshopper_encrypt_block(&ctx->encrypt_round_keys, &tmp,
586                               buf, &ctx->buffer);
587     memcpy(iv, buf, 16);
588 }
589
590 int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out,
591                                    const unsigned char *in, size_t inl)
592 {
593     gost_grasshopper_cipher_ctx *c = (gost_grasshopper_cipher_ctx *)
594         EVP_CIPHER_CTX_get_cipher_data(ctx);
595     const unsigned char *in_ptr = in;
596     unsigned char *out_ptr = out;
597     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
598     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
599     int num = EVP_CIPHER_CTX_num(ctx);
600     size_t i = 0;
601     size_t j;
602
603     /* process partial block if any */
604     if (num > 0) {
605         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
606              j++, i++, in_ptr++, out_ptr++) {
607             *out_ptr = buf[j] ^ (*in_ptr);
608         }
609         if (j == GRASSHOPPER_BLOCK_SIZE) {
610             EVP_CIPHER_CTX_set_num(ctx, 0);
611         } else {
612             EVP_CIPHER_CTX_set_num(ctx, (int)j);
613             return 1;
614         }
615     }
616
617     for (; i + GRASSHOPPER_BLOCK_SIZE <
618          inl;
619          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
620          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
621         /*
622          * block cipher current iv
623          */
624         /* Encrypt */
625         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
626                                   (grasshopper_w128_t *) buf);
627
628         /*
629          * xor next block of input text with it and output it
630          */
631         /*
632          * output this block
633          */
634         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
635             out_ptr[j] = buf[j] ^ in_ptr[j];
636         }
637     }
638
639     /* Process rest of buffer */
640     if (i < inl) {
641         gost_grasshopper_cnt_next(c, (grasshopper_w128_t *) iv,
642                                   (grasshopper_w128_t *) buf);
643         for (j = 0; i < inl; j++, i++) {
644             out_ptr[j] = buf[j] ^ in_ptr[j];
645         }
646         EVP_CIPHER_CTX_set_num(ctx, (int)j);
647     } else {
648         EVP_CIPHER_CTX_set_num(ctx, 0);
649     }
650
651     return 1;
652 }
653
654 int gost_grasshopper_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
655                                    const unsigned char *in, size_t inl)
656 {
657     gost_grasshopper_cipher_ctx *c =
658         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
659     const unsigned char *in_ptr = in;
660     unsigned char *out_ptr = out;
661     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
662     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
663     bool encrypting = (bool) EVP_CIPHER_CTX_encrypting(ctx);
664     int num = EVP_CIPHER_CTX_num(ctx);
665     size_t i = 0;
666     size_t j = 0;
667
668     /* process partial block if any */
669     if (num > 0) {
670         for (j = (size_t)num, i = 0; j < GRASSHOPPER_BLOCK_SIZE && i < inl;
671              j++, i++, in_ptr++, out_ptr++) {
672             if (!encrypting) {
673                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *in_ptr;
674             }
675             *out_ptr = buf[j] ^ (*in_ptr);
676             if (encrypting) {
677                 buf[j + GRASSHOPPER_BLOCK_SIZE] = *out_ptr;
678             }
679         }
680         if (j == GRASSHOPPER_BLOCK_SIZE) {
681             memcpy(iv, buf + GRASSHOPPER_BLOCK_SIZE, GRASSHOPPER_BLOCK_SIZE);
682             EVP_CIPHER_CTX_set_num(ctx, 0);
683         } else {
684             EVP_CIPHER_CTX_set_num(ctx, (int)j);
685             return 1;
686         }
687     }
688
689     for (; i + GRASSHOPPER_BLOCK_SIZE <
690          inl;
691          i += GRASSHOPPER_BLOCK_SIZE, in_ptr +=
692          GRASSHOPPER_BLOCK_SIZE, out_ptr += GRASSHOPPER_BLOCK_SIZE) {
693         /*
694          * block cipher current iv
695          */
696         grasshopper_encrypt_block(&c->encrypt_round_keys,
697                                   (grasshopper_w128_t *) iv,
698                                   (grasshopper_w128_t *) buf, &c->buffer);
699         /*
700          * xor next block of input text with it and output it
701          */
702         /*
703          * output this block
704          */
705         if (!encrypting) {
706             memcpy(iv, in_ptr, GRASSHOPPER_BLOCK_SIZE);
707         }
708         for (j = 0; j < GRASSHOPPER_BLOCK_SIZE; j++) {
709             out_ptr[j] = buf[j] ^ in_ptr[j];
710         }
711         /* Encrypt */
712         /* Next iv is next block of cipher text */
713         if (encrypting) {
714             memcpy(iv, out_ptr, GRASSHOPPER_BLOCK_SIZE);
715         }
716     }
717
718     /* Process rest of buffer */
719     if (i < inl) {
720         grasshopper_encrypt_block(&c->encrypt_round_keys,
721                                   (grasshopper_w128_t *) iv,
722                                   (grasshopper_w128_t *) buf, &c->buffer);
723         if (!encrypting) {
724             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, in_ptr, inl - i);
725         }
726         for (j = 0; i < inl; j++, i++) {
727             out_ptr[j] = buf[j] ^ in_ptr[j];
728         }
729         EVP_CIPHER_CTX_set_num(ctx, (int)j);
730         if (encrypting) {
731             memcpy(buf + GRASSHOPPER_BLOCK_SIZE, out_ptr, j);
732         }
733     } else {
734         EVP_CIPHER_CTX_set_num(ctx, 0);
735     }
736
737     return 1;
738 }
739
740 int gost_grasshopper_cipher_cleanup(EVP_CIPHER_CTX *ctx)
741 {
742     gost_grasshopper_cipher_ctx *c =
743         (gost_grasshopper_cipher_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
744
745     if (!c)
746         return 1;
747
748     if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE)
749         gost_grasshopper_cipher_destroy_ctr(c);
750
751     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
752
753     return 1;
754 }
755
756 int gost_grasshopper_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
757 {
758         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
759                 gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
760
761                 /* CMS implies 256kb section_size */
762                 ctr->section_size = 256*1024;
763
764                 return gost2015_set_asn1_params(params, EVP_CIPHER_CTX_original_iv(ctx), 8,
765                                 ctr->kdf_seed);
766         }
767         return 0;
768 }
769
770 GRASSHOPPER_INLINE int gost_grasshopper_get_asn1_parameters(EVP_CIPHER_CTX
771                                                             *ctx, ASN1_TYPE
772                                                             *params)
773 {
774         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CTR_MODE) {
775                 gost_grasshopper_cipher_ctx_ctr *ctr = EVP_CIPHER_CTX_get_cipher_data(ctx);
776
777                 int iv_len = 16;
778                 unsigned char iv[16];
779
780                 if (gost2015_get_asn1_params(params, 16, iv, 8, ctr->kdf_seed) == 0) {
781                         return 0;
782                 }
783
784                 memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, iv_len);
785                 memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, iv_len);
786
787                 /* CMS implies 256kb section_size */
788                 ctr->section_size = 256*1024;
789                 return 1;
790         }
791         return 0;
792 }
793
794 int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
795 {
796     switch (type) {
797     case EVP_CTRL_RAND_KEY:{
798             if (RAND_priv_bytes
799                 ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
800                 GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, GOST_R_RNG_ERROR);
801                 return -1;
802             }
803             break;
804         }
805     case EVP_CTRL_KEY_MESH:{
806             gost_grasshopper_cipher_ctx_ctr *c =
807                 EVP_CIPHER_CTX_get_cipher_data(ctx);
808             if ((c->c.type != GRASSHOPPER_CIPHER_CTRACPKM &&
809                                                     c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
810                                                     || (arg == 0)
811                 || (arg % GRASSHOPPER_BLOCK_SIZE))
812                 return -1;
813             c->section_size = arg;
814             break;
815         }
816 #ifdef EVP_CTRL_TLS1_2_TLSTREE
817     case EVP_CTRL_TLS1_2_TLSTREE:
818         {
819           unsigned char newkey[32];
820           int mode = EVP_CIPHER_CTX_mode(ctx);
821           static const unsigned char zeroseq[8];
822           gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL;
823           gost_grasshopper_cipher_ctx *c = NULL;
824
825           unsigned char adjusted_iv[16];
826           unsigned char seq[8];
827           int j, carry;
828           if (mode != EVP_CIPH_CTR_MODE)
829             return -1;
830
831           ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *)
832             EVP_CIPHER_CTX_get_cipher_data(ctx);
833           c = &(ctr_ctx->c);
834
835           memcpy(seq, ptr, 8);
836           if (EVP_CIPHER_CTX_encrypting(ctx)) {
837             /*
838              * OpenSSL increments seq after mac calculation.
839              * As we have Mac-Then-Encrypt, we need decrement it here on encryption
840              * to derive the key correctly.
841              * */
842             if (memcmp(seq, zeroseq, 8) != 0)
843             {
844               for(j=7; j>=0; j--)
845               {
846                 if (seq[j] != 0) {seq[j]--; break;}
847                 else seq[j]  = 0xFF;
848               }
849             }
850           }
851           if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey,
852                 (const unsigned char *)seq) > 0) {
853             memset(adjusted_iv, 0, 16);
854             memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8);
855             for(j=7,carry=0; j>=0; j--)
856             {
857               int adj_byte = adjusted_iv[j]+seq[j]+carry;
858               carry = (adj_byte > 255) ? 1 : 0;
859               adjusted_iv[j] = adj_byte & 0xFF;
860             }
861             EVP_CIPHER_CTX_set_num(ctx, 0);
862             memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 16);
863
864             gost_grasshopper_cipher_key(c, newkey);
865             return 1;
866           }
867         }
868         return -1;
869 #endif
870 #if 0
871     case EVP_CTRL_AEAD_GET_TAG:
872     case EVP_CTRL_AEAD_SET_TAG:
873         {
874             int taglen = arg;
875             unsigned char *tag = ptr;
876
877             gost_grasshopper_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
878             if (c->c.type != GRASSHOPPER_CIPHER_MGM)
879                 return -1;
880
881             if (taglen > KUZNYECHIK_MAC_MAX_SIZE) {
882                 CRYPTOCOMerr(CRYPTOCOM_F_GOST_GRASSHOPPER_CIPHER_CTL,
883                         CRYPTOCOM_R_INVALID_TAG_LENGTH);
884                 return -1;
885             }
886
887             if (type == EVP_CTRL_AEAD_GET_TAG)
888                 memcpy(tag, c->final_tag, taglen);
889             else
890                 memcpy(c->final_tag, tag, taglen);
891
892             return 1;
893         }
894 #endif
895                 case EVP_CTRL_PROCESS_UNPROTECTED:
896     {
897       STACK_OF(X509_ATTRIBUTE) *x = ptr;
898       gost_grasshopper_cipher_ctx_ctr *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
899
900       if (c->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
901         return -1;
902
903       return gost2015_process_unprotected_attributes(x, arg, KUZNYECHIK_MAC_MAX_SIZE, c->tag);
904     }
905     return 1;
906     case EVP_CTRL_COPY: {
907                         EVP_CIPHER_CTX *out = ptr;
908
909       gost_grasshopper_cipher_ctx_ctr *out_cctx = EVP_CIPHER_CTX_get_cipher_data(out);
910       gost_grasshopper_cipher_ctx_ctr *in_cctx  = EVP_CIPHER_CTX_get_cipher_data(ctx);
911
912       if (in_cctx->c.type != GRASSHOPPER_CIPHER_CTRACPKMOMAC)
913           return -1;
914
915                         if (in_cctx->omac_ctx == out_cctx->omac_ctx) {
916                                 out_cctx->omac_ctx = EVP_MD_CTX_new();
917                                 if (out_cctx->omac_ctx == NULL) {
918                                         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL, ERR_R_MALLOC_FAILURE);
919                                         return -1;
920                                 }
921                         }
922                         return EVP_MD_CTX_copy(out_cctx->omac_ctx, in_cctx->omac_ctx);
923                 }
924     default:
925         GOSTerr(GOST_F_GOST_GRASSHOPPER_CIPHER_CTL,
926                 GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
927         return -1;
928     }
929     return 1;
930 }
931
932 const GRASSHOPPER_INLINE EVP_CIPHER *cipher_gost_grasshopper_ctracpkm()
933 {
934     return GOST_init_cipher(&grasshopper_ctr_acpkm_cipher);
935 }
936 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */