Malleable keys: Crypted R parameter support.
[novacoin.git] / src / ecies.cpp
1 /**
2  * @file /cryptron/ecies.c
3  *
4  * @brief ECIES encryption/decryption functions.
5  *
6  * $Author: Ladar Levison $
7  * $Website: http://lavabit.com $
8  *
9  */
10
11 #include "ies.h"
12 #include <iostream>
13 #include <vector>
14 #include <openssl/ecdh.h>
15
16 #define SET_ERROR(string) \
17     sprintf(error, "%s %s:%d", (string), __FILE__, __LINE__)
18 #define SET_OSSL_ERROR(string) \
19     sprintf(error, "%s {error = %s} %s:%d", (string), ERR_error_string(ERR_get_error(), NULL), __FILE__, __LINE__)
20
21 /* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
22  * Taken from openssl/crypto/ecdh/ech_kdf.c in github:openssl/openssl
23  * ffa08b3242e0f10f1fef3c93ef3f0b51de8c27a9 */
24
25 /* Key derivation function from X9.62/SECG */
26 /* Way more than we will ever need */
27 #define ECDH_KDF_MAX (1 << 30)
28 int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
29                    const unsigned char *Z, size_t Zlen,
30                    const unsigned char *sinfo, size_t sinfolen,
31                    const EVP_MD *md)
32 {
33     EVP_MD_CTX mctx;
34     int rv = 0;
35     unsigned int i;
36     size_t mdlen;
37     unsigned char ctr[4];
38     if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX || Zlen > ECDH_KDF_MAX)
39         return 0;
40     mdlen = EVP_MD_size(md);
41     EVP_MD_CTX_init(&mctx);
42     for (i = 1;;i++)
43     {
44         unsigned char mtmp[EVP_MAX_MD_SIZE];
45         EVP_DigestInit_ex(&mctx, md, NULL);
46         ctr[3] = i & 0xFF;
47         ctr[2] = (i >> 8) & 0xFF;
48         ctr[1] = (i >> 16) & 0xFF;
49         ctr[0] = (i >> 24) & 0xFF;
50         if (!EVP_DigestUpdate(&mctx, Z, Zlen))
51             goto err;
52         if (!EVP_DigestUpdate(&mctx, ctr, sizeof(ctr)))
53             goto err;
54         if (!EVP_DigestUpdate(&mctx, sinfo, sinfolen))
55             goto err;
56         if (outlen >= mdlen)
57         {
58             if (!EVP_DigestFinal(&mctx, out, NULL))
59                 goto err;
60             outlen -= mdlen;
61             if (outlen == 0)
62                 break;
63             out += mdlen;
64         }
65         else
66         {
67             if (!EVP_DigestFinal(&mctx, mtmp, NULL))
68                 goto err;
69             memcpy(out, mtmp, outlen);
70             OPENSSL_cleanse(mtmp, mdlen);
71             break;
72         }
73     }
74     rv = 1;
75   err:
76     EVP_MD_CTX_cleanup(&mctx);
77     return rv;
78 }
79
80 static size_t envelope_key_len(const ies_ctx_t *ctx)
81 {
82     return EVP_CIPHER_key_length(ctx->cipher) + EVP_MD_size(ctx->md);
83 }
84
85 static EC_KEY * ecies_key_create(const EC_KEY *user, char *error) {
86
87     const EC_GROUP *group;
88     EC_KEY *key = NULL;
89
90     if (!(key = EC_KEY_new())) {
91         SET_OSSL_ERROR("EC_KEY_new failed");
92         return NULL;
93     }
94
95     if (!(group = EC_KEY_get0_group(user))) {
96         SET_ERROR("The user key does not have group");
97         EC_KEY_free(key);
98         return NULL;
99     }
100
101     if (EC_KEY_set_group(key, group) != 1) {
102         SET_OSSL_ERROR("EC_KEY_set_group failed");
103         EC_KEY_free(key);
104         return NULL;
105     }
106
107     if (EC_KEY_generate_key(key) != 1) {
108         SET_OSSL_ERROR("EC_KEY_generate_key failed");
109         EC_KEY_free(key);
110         return NULL;
111     }
112
113     return key;
114 }
115
116 static unsigned char *prepare_envelope_key(const ies_ctx_t *ctx, cryptogram_t *cryptogram, char *error)
117 {
118
119     const size_t key_buf_len = envelope_key_len(ctx);
120     const size_t ecdh_key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ctx->user_key)) + 7) / 8;
121     unsigned char *envelope_key = NULL, *ktmp = NULL;
122     EC_KEY *ephemeral = NULL;
123     size_t written_length;
124
125     /* High-level ECDH via EVP does not allow use of arbitrary KDF function.
126      * We should use low-level API for KDF2
127      * c.f. openssl/crypto/ec/ec_pmeth.c */
128     if ((envelope_key = (unsigned char *) OPENSSL_malloc(key_buf_len)) == NULL) {
129         SET_ERROR("Failed to allocate memory for envelope_key");
130         goto err;
131     }
132
133     if (!(ephemeral = ecies_key_create(ctx->user_key, error))) {
134         goto err;
135     }
136
137     /* key agreement and KDF
138      * reference: openssl/crypto/ec/ec_pmeth.c */
139     ktmp = (unsigned char *) OPENSSL_malloc(ecdh_key_len);
140     if (ktmp == NULL) {
141         SET_ERROR("No memory for ECDH temporary key");
142         goto err;
143     }
144
145     if (ECDH_compute_key(ktmp, ecdh_key_len, EC_KEY_get0_public_key(ctx->user_key), ephemeral, NULL)
146         != (int)ecdh_key_len) {
147         SET_OSSL_ERROR("An error occurred while ECDH_compute_key");
148         goto err;
149     }
150
151     /* equals to ISO 18033-2 KDF2 */
152     if (!ECDH_KDF_X9_62(envelope_key, key_buf_len, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
153         SET_OSSL_ERROR("Failed to stretch with KDF2");
154         goto err;
155     }
156
157     /* Store the public key portion of the ephemeral key. */
158     written_length = EC_POINT_point2oct(
159         EC_KEY_get0_group(ephemeral),
160         EC_KEY_get0_public_key(ephemeral),
161         POINT_CONVERSION_COMPRESSED,
162         cryptogram_key_data(cryptogram),
163         ctx->stored_key_length,
164         NULL);
165     if (written_length == 0) {
166         SET_OSSL_ERROR("Error while recording the public portion of the envelope key");
167         goto err;
168     }
169     if (written_length != ctx->stored_key_length) {
170         SET_ERROR("Written envelope key length does not match with expected");
171         goto err;
172     }
173
174     EC_KEY_free(ephemeral);
175     OPENSSL_cleanse(ktmp, ecdh_key_len);
176     OPENSSL_free(ktmp);
177
178     return envelope_key;
179
180   err:
181     if (ephemeral)
182         EC_KEY_free(ephemeral);
183     if (envelope_key) {
184         OPENSSL_cleanse(envelope_key, key_buf_len);
185         OPENSSL_free(envelope_key);
186     }
187     if (ktmp) {
188         OPENSSL_cleanse(ktmp, ecdh_key_len);
189         OPENSSL_free(ktmp);
190     }
191     return NULL;
192 }
193
194 static int store_cipher_body(
195     const ies_ctx_t *ctx,
196     const unsigned char *envelope_key,
197     const unsigned char *data,
198     size_t length,
199     cryptogram_t *cryptogram,
200     char *error)
201 {
202     int out_len, len_sum = 0;
203     size_t expected_len = cryptogram_body_length(cryptogram);
204     unsigned char iv[EVP_MAX_IV_LENGTH];
205     EVP_CIPHER_CTX cipher;
206     unsigned char *body;
207
208     /* For now we use an empty initialization vector. */
209     memset(iv, 0, EVP_MAX_IV_LENGTH);
210
211     EVP_CIPHER_CTX_init(&cipher);
212     body = cryptogram_body_data(cryptogram);
213
214     if (EVP_EncryptInit_ex(&cipher, ctx->cipher, NULL, envelope_key, iv) != 1
215         || EVP_EncryptUpdate(&cipher, body, &out_len, data, length) != 1) {
216         SET_OSSL_ERROR("Error while trying to secure the data using the symmetric cipher");
217         EVP_CIPHER_CTX_cleanup(&cipher);
218         return 0;
219     }
220
221     if (expected_len < (size_t)out_len) {
222         SET_ERROR("The symmetric cipher overflowed");
223         EVP_CIPHER_CTX_cleanup(&cipher);
224         return 0;
225     }
226
227     body += out_len;
228     len_sum += out_len;
229     if (EVP_EncryptFinal_ex(&cipher, body, &out_len) != 1) {
230         SET_OSSL_ERROR("Error while finalizing the data using the symmetric cipher");
231         EVP_CIPHER_CTX_cleanup(&cipher);
232         cryptogram_free(cryptogram);
233         return 0;
234     }
235
236     EVP_CIPHER_CTX_cleanup(&cipher);
237
238     if (expected_len < (size_t)len_sum) {
239         SET_ERROR("The symmetric cipher overflowed");
240         return 0;
241     }
242
243     return 1;
244 }
245
246 static int store_mac_tag(const ies_ctx_t *ctx, const unsigned char *envelope_key, cryptogram_t *cryptogram, char *error) {
247     const size_t key_offset = EVP_CIPHER_key_length(ctx->cipher);
248     const size_t key_length = EVP_MD_size(ctx->md);
249     const size_t mac_length = cryptogram_mac_length(cryptogram);
250     unsigned int out_len;
251     HMAC_CTX hmac;
252
253     HMAC_CTX_init(&hmac);
254
255     /* Generate hash tag using encrypted data */
256     if (HMAC_Init_ex(&hmac, envelope_key + key_offset, key_length, ctx->md, NULL) != 1
257         || HMAC_Update(&hmac, cryptogram_body_data(cryptogram), cryptogram_body_length(cryptogram)) != 1
258         || HMAC_Final(&hmac, cryptogram_mac_data(cryptogram), &out_len) != 1) {
259         SET_OSSL_ERROR("Unable to generate tag");
260         HMAC_CTX_cleanup(&hmac);
261         return 0;
262     }
263
264     HMAC_CTX_cleanup(&hmac);
265
266     if (out_len != mac_length) {
267         SET_ERROR("MAC length expectation does not meet");
268         return 0;
269     }
270
271     return 1;
272 }
273
274 cryptogram_t * ecies_encrypt(const ies_ctx_t *ctx, const unsigned char *data, size_t length, char *error) {
275
276     const size_t block_length = EVP_CIPHER_block_size(ctx->cipher);
277     const size_t mac_length = EVP_MD_size(ctx->md);
278     cryptogram_t *cryptogram = NULL;
279     unsigned char *envelope_key = NULL;
280
281     if (!ctx || !data || !length) {
282         SET_ERROR("Invalid arguments");
283         return NULL;
284     }
285
286     if (block_length == 0 || block_length > EVP_MAX_BLOCK_LENGTH) {
287         SET_ERROR("Derived block size is incorrect");
288         return NULL;
289     }
290
291     cryptogram = cryptogram_alloc(ctx->stored_key_length,
292                                   mac_length,
293                                   length + (length % block_length ? (block_length - (length % block_length)) : 0));
294     if (!cryptogram) {
295         SET_ERROR("Unable to allocate a cryptogram_t buffer to hold the encrypted result.");
296         goto err;
297     }
298
299     if ((envelope_key = prepare_envelope_key(ctx, cryptogram, error)) == NULL) {
300         goto err;
301     }
302
303     if (!store_cipher_body(ctx, envelope_key, data, length, cryptogram, error)) {
304         goto err;
305     }
306
307     if (!store_mac_tag(ctx, envelope_key, cryptogram, error)) {
308         goto err;
309     }
310
311     OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
312     OPENSSL_free(envelope_key);
313
314     return cryptogram;
315
316   err:
317     if (cryptogram)
318         cryptogram_free(cryptogram);
319     if (envelope_key) {
320         OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
321         OPENSSL_free(envelope_key);
322     }
323     return NULL;
324 }
325
326 static EC_KEY *ecies_key_create_public_octets(EC_KEY *user, unsigned char *octets, size_t length, char *error) {
327
328     EC_KEY *key = NULL;
329     EC_POINT *point = NULL;
330     const EC_GROUP *group = NULL;
331
332     if (!(key = EC_KEY_new())) {
333         SET_OSSL_ERROR("Cannot create instance for ephemeral key");
334         return NULL;
335     }
336
337     if (!(group = EC_KEY_get0_group(user))) {
338         SET_ERROR("Cannot get group from user key");
339         EC_KEY_free(key);
340         return NULL;
341     }
342
343     if (EC_KEY_set_group(key, group) != 1) {
344         SET_OSSL_ERROR("EC_KEY_set_group failed");
345         EC_KEY_free(key);
346         return NULL;
347     }
348
349     if (!(point = EC_POINT_new(group))) {
350         SET_OSSL_ERROR("EC_POINT_new failed");
351         EC_KEY_free(key);
352         return NULL;
353     }
354
355     if (EC_POINT_oct2point(group, point, octets, length, NULL) != 1) {
356         SET_OSSL_ERROR("EC_POINT_oct2point failed");
357         EC_KEY_free(key);
358         return NULL;
359     }
360
361     if (EC_KEY_set_public_key(key, point) != 1) {
362         SET_OSSL_ERROR("EC_KEY_set_public_key failed");
363         EC_POINT_free(point);
364         EC_KEY_free(key);
365         return NULL;
366     }
367
368     EC_POINT_free(point);
369
370     if (EC_KEY_check_key(key) != 1) {
371         SET_OSSL_ERROR("EC_KEY_check_key failed");
372         EC_KEY_free(key);
373         return NULL;
374     }
375
376     return key;
377 }
378
379 unsigned char *restore_envelope_key(const ies_ctx_t *ctx, const cryptogram_t *cryptogram, char *error)
380 {
381
382     const size_t key_buf_len = envelope_key_len(ctx);
383     const size_t ecdh_key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ctx->user_key)) + 7) / 8;
384     EC_KEY *ephemeral = NULL, *user_copy = NULL;
385     unsigned char *envelope_key = NULL, *ktmp = NULL;
386
387     if ((envelope_key = (unsigned char *) OPENSSL_malloc(key_buf_len)) == NULL) {
388         SET_ERROR("Failed to allocate memory for envelope_key");
389         goto err;
390     }
391
392     if (!(user_copy = EC_KEY_new())) {
393         SET_OSSL_ERROR("Failed to create instance for user key copy");
394         goto err;
395     }
396
397     if (!(EC_KEY_copy(user_copy, ctx->user_key))) {
398         SET_OSSL_ERROR("Failed to copy user key");
399         goto err;
400     }
401
402     if (!(ephemeral = ecies_key_create_public_octets(user_copy, cryptogram_key_data(cryptogram), cryptogram_key_length(cryptogram), error))) {
403         goto err;
404     }
405
406     /* key agreement and KDF
407      * reference: openssl/crypto/ec/ec_pmeth.c */
408     ktmp = (unsigned char *) OPENSSL_malloc(ecdh_key_len);
409     if (ktmp == NULL) {
410         SET_ERROR("No memory for ECDH temporary key");
411         goto err;
412     }
413
414     if (ECDH_compute_key(ktmp, ecdh_key_len, EC_KEY_get0_public_key(ephemeral), user_copy, NULL)
415         != (int)ecdh_key_len) {
416         SET_OSSL_ERROR("An error occurred while ECDH_compute_key");
417         goto err;
418     }
419
420     /* equals to ISO 18033-2 KDF2 */
421     if (!ECDH_KDF_X9_62(envelope_key, key_buf_len, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
422         SET_OSSL_ERROR("Failed to stretch with KDF2");
423         goto err;
424     }
425
426     EC_KEY_free(user_copy);
427     EC_KEY_free(ephemeral);
428     OPENSSL_cleanse(ktmp, ecdh_key_len);
429     OPENSSL_free(ktmp);
430
431     return envelope_key;
432
433   err:
434     if (ephemeral)
435         EC_KEY_free(ephemeral);
436     if (user_copy)
437         EC_KEY_free(user_copy);
438     if (envelope_key) {
439         OPENSSL_cleanse(envelope_key, key_buf_len);
440         OPENSSL_free(envelope_key);
441     }
442     if (ktmp) {
443         OPENSSL_cleanse(ktmp, ecdh_key_len);
444         OPENSSL_free(ktmp);
445     }
446     return NULL;
447 }
448
449 static int verify_mac(const ies_ctx_t *ctx, const cryptogram_t *cryptogram, const unsigned char * envelope_key, char *error)
450 {
451     const size_t key_offset = EVP_CIPHER_key_length(ctx->cipher);
452     const size_t key_length = EVP_MD_size(ctx->md);
453     const size_t mac_length = cryptogram_mac_length(cryptogram);
454     unsigned int out_len;
455     HMAC_CTX hmac;
456     unsigned char md[EVP_MAX_MD_SIZE];
457
458     HMAC_CTX_init(&hmac);
459
460     /* Generate hash tag using encrypted data */
461     if (HMAC_Init_ex(&hmac, envelope_key + key_offset, key_length, ctx->md, NULL) != 1
462         || HMAC_Update(&hmac, cryptogram_body_data(cryptogram), cryptogram_body_length(cryptogram)) != 1
463         || HMAC_Final(&hmac, md, &out_len) != 1) {
464         SET_OSSL_ERROR("Unable to generate tag");
465         HMAC_CTX_cleanup(&hmac);
466         return 0;
467     }
468
469     HMAC_CTX_cleanup(&hmac);
470
471     if (out_len != mac_length) {
472         SET_ERROR("MAC length expectation does not meet");
473         return 0;
474     }
475
476     if (memcmp(md, cryptogram_mac_data(cryptogram), mac_length) != 0) {
477         SET_ERROR("MAC tag verification failed");
478         return 0;
479     }
480
481     return 1;
482 }
483
484 unsigned char *decrypt_body(const ies_ctx_t *ctx, const cryptogram_t *cryptogram, const unsigned char *envelope_key, size_t *length, char *error)
485 {
486     int out_len;
487     size_t output_sum;
488     const size_t body_length = cryptogram_body_length(cryptogram);
489     unsigned char iv[EVP_MAX_IV_LENGTH], *block, *output;
490     EVP_CIPHER_CTX cipher;
491
492     if (!(output = (unsigned char*)malloc(body_length + 1))) {
493         SET_ERROR("Failed to allocate memory for clear text");
494         return NULL;
495     }
496
497     /* For now we use an empty initialization vector */
498     memset(iv, 0, EVP_MAX_IV_LENGTH);
499     memset(output, 0, body_length + 1);
500
501     EVP_CIPHER_CTX_init(&cipher);
502
503     block = output;
504     if (EVP_DecryptInit_ex(&cipher, ctx->cipher, NULL, envelope_key, iv) != 1
505         || EVP_DecryptUpdate(&cipher, block, &out_len, cryptogram_body_data(cryptogram), body_length) != 1) {
506         SET_OSSL_ERROR("Unable to decrypt");
507         EVP_CIPHER_CTX_cleanup(&cipher);
508         free(output);
509         return NULL;
510     }
511     output_sum = out_len;
512
513     block += output_sum;
514     if (EVP_DecryptFinal_ex(&cipher, block, &out_len) != 1) {
515         printf("Unable to decrypt the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
516         EVP_CIPHER_CTX_cleanup(&cipher);
517         free(output);
518         return NULL;
519     }
520     output_sum += out_len;
521
522     EVP_CIPHER_CTX_cleanup(&cipher);
523
524     *length = output_sum;
525
526     return output;
527 }
528
529 unsigned char * ecies_decrypt(const ies_ctx_t *ctx, const cryptogram_t *cryptogram, size_t *length, char *error)
530 {
531     unsigned char *envelope_key = NULL, *output = NULL;
532
533     if (!ctx || !cryptogram || !length || !error) {
534         SET_ERROR("Invalid argument");
535         goto err;
536     }
537
538     envelope_key = restore_envelope_key(ctx, cryptogram, error);
539     if (envelope_key == NULL) {
540         goto err;
541     }
542
543     if (!verify_mac(ctx, cryptogram, envelope_key, error)) {
544         goto err;
545     }
546
547     if ((output = decrypt_body(ctx, cryptogram, envelope_key, length, error)) == NULL) {
548         goto err;
549     }
550
551   err:
552     OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
553     OPENSSL_free(envelope_key);
554
555     return output;
556 }
557
558 ies_ctx_t *create_context(EC_KEY *user_key)
559 {
560     ies_ctx_t* ctx = (ies_ctx_t*) malloc(sizeof(ies_ctx_t));
561     ctx->cipher = EVP_aes_128_cbc();
562     ctx->md = EVP_sha1();
563     ctx->kdf_md = EVP_sha1();
564     ctx->stored_key_length = 33;
565     ctx->user_key = user_key;
566
567     return ctx;
568 }