Key generation re-work to handle parameters and 2 stage keygen
[platform/core/security/yaca.git] / src / key.c
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19 /**
20  * @file key.c
21  * @brief
22  */
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28 #include <stdbool.h>
29
30 #include <openssl/evp.h>
31 #include <openssl/rsa.h>
32 #include <openssl/bio.h>
33 #include <openssl/pem.h>
34 #include <openssl/des.h>
35 #include <openssl/dh.h>
36
37 #include <yaca_crypto.h>
38 #include <yaca_error.h>
39 #include <yaca_key.h>
40 #include <yaca_types.h>
41
42 #include "internal.h"
43
44 struct openssl_password_data {
45         bool password_requested;
46         const char *password;
47 };
48
49 int openssl_password_cb(char *buf, int size, UNUSED int rwflag, void *u)
50 {
51         struct openssl_password_data *cb_data = u;
52
53         if (cb_data->password == NULL)
54                 return 0;
55
56         size_t pass_len = strlen(cb_data->password);
57
58         if (pass_len > INT_MAX || (int)pass_len > size)
59                 return 0;
60
61         memcpy(buf, cb_data->password, pass_len);
62         cb_data->password_requested = true;
63
64         return pass_len;
65 }
66
67 int openssl_password_cb_error(UNUSED char *buf, UNUSED int size, UNUSED int rwflag, UNUSED void *u)
68 {
69         return 0;
70 }
71
72 static const struct {
73         size_t ec;
74         int nid;
75 } EC_NID_PAIRS[] = {
76         {YACA_KEY_LENGTH_EC_PRIME192V1, NID_X9_62_prime192v1},
77         {YACA_KEY_LENGTH_EC_PRIME256V1, NID_X9_62_prime256v1},
78         {YACA_KEY_LENGTH_EC_SECP256K1,  NID_secp256k1},
79         {YACA_KEY_LENGTH_EC_SECP384R1,  NID_secp384r1},
80         {YACA_KEY_LENGTH_EC_SECP521R1,  NID_secp521r1}
81 };
82
83 static const size_t EC_NID_PAIRS_SIZE = sizeof(EC_NID_PAIRS) / sizeof(EC_NID_PAIRS[0]);
84
85 static const struct {
86         int evp_id;
87         yaca_key_type_e priv;
88         yaca_key_type_e pub;
89         yaca_key_type_e params;
90 } KEY_TYPES_PARAMS[] = {
91         {EVP_PKEY_RSA, YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_TYPE_RSA_PUB, -1},
92         {EVP_PKEY_DSA, YACA_KEY_TYPE_DSA_PRIV, YACA_KEY_TYPE_DSA_PUB, YACA_KEY_TYPE_DSA_PARAMS},
93         {EVP_PKEY_DH,  YACA_KEY_TYPE_DH_PRIV,  YACA_KEY_TYPE_DH_PUB,  YACA_KEY_TYPE_DH_PARAMS},
94         {EVP_PKEY_EC,  YACA_KEY_TYPE_EC_PRIV,  YACA_KEY_TYPE_EC_PUB,  YACA_KEY_TYPE_EC_PARAMS}
95 };
96
97 static const size_t KEY_TYPES_PARAMS_SIZE = sizeof(KEY_TYPES_PARAMS) / sizeof(KEY_TYPES_PARAMS[0]);
98
99 #define CONVERT_TYPES_TEMPLATE(data, src_type, src, dst_type, dst) \
100         static int convert_##src##_to_##dst (src_type src, dst_type *dst) \
101         { \
102                 assert(dst != NULL); \
103                 size_t i; \
104                 for (i = 0; i < data##_SIZE; ++i) \
105                         if (data[i].src == src) { \
106                                 if (data[i].dst != (dst_type)-1) { \
107                                         *dst = data[i].dst; \
108                                         return YACA_ERROR_NONE; \
109                                 } \
110                         } \
111                 return YACA_ERROR_INVALID_PARAMETER; \
112         }
113
114 CONVERT_TYPES_TEMPLATE(EC_NID_PAIRS, int, nid, size_t, ec)
115 CONVERT_TYPES_TEMPLATE(EC_NID_PAIRS, size_t, ec, int, nid)
116
117 CONVERT_TYPES_TEMPLATE(KEY_TYPES_PARAMS, yaca_key_type_e, params, int, evp_id)
118 CONVERT_TYPES_TEMPLATE(KEY_TYPES_PARAMS, yaca_key_type_e, priv,   int, evp_id)
119 CONVERT_TYPES_TEMPLATE(KEY_TYPES_PARAMS, yaca_key_type_e, params, yaca_key_type_e, priv)
120
121 int base64_decode_length(const char *data, size_t data_len, size_t *len)
122 {
123         assert(data != NULL);
124         assert(data_len != 0);
125         assert(len != NULL);
126
127         size_t padded = 0;
128         size_t tmp_len = data_len;
129
130         if (data_len % 4 != 0)
131                 return YACA_ERROR_INVALID_PARAMETER;
132
133         if (data[tmp_len - 1] == '=') {
134                 padded = 1;
135                 if (data[tmp_len - 2] == '=')
136                         padded = 2;
137         }
138
139         *len = data_len / 4 * 3 - padded;
140         return YACA_ERROR_NONE;
141 }
142
143 #define TMP_BUF_LEN 512
144
145 int base64_decode(const char *data, size_t data_len, BIO **output)
146 {
147         assert(data != NULL);
148         assert(data_len != 0);
149         assert(output != NULL);
150
151         int ret;
152         BIO *b64 = NULL;
153         BIO *src = NULL;
154         BIO *dst = NULL;
155         char tmpbuf[TMP_BUF_LEN];
156         size_t b64_len;
157         char *out;
158         long out_len;
159
160         /* This is because of BIO_new_mem_buf() having its length param typed int */
161         if (data_len > INT_MAX)
162                 return YACA_ERROR_INVALID_PARAMETER;
163
164         /* First phase of correctness checking, calculate expected output length */
165         ret = base64_decode_length(data, data_len, &b64_len);
166         if (ret != YACA_ERROR_NONE)
167                 return ret;
168
169         b64 = BIO_new(BIO_f_base64());
170         if (b64 == NULL) {
171                 ret = YACA_ERROR_INTERNAL;
172                 ERROR_DUMP(ret);
173                 return ret;
174         }
175
176         src = BIO_new_mem_buf(data, data_len);
177         if (src == NULL) {
178                 ret = YACA_ERROR_INTERNAL;
179                 ERROR_DUMP(ret);
180                 goto exit;
181         }
182
183         BIO_push(b64, src);
184
185         dst = BIO_new(BIO_s_mem());
186         if (dst == NULL) {
187                 ret = YACA_ERROR_INTERNAL;
188                 ERROR_DUMP(ret);
189                 goto exit;
190         }
191
192         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
193
194         /* Try to decode */
195         for (;;) {
196                 ret = BIO_read(b64, tmpbuf, TMP_BUF_LEN);
197                 if (ret < 0) {
198                         ret = YACA_ERROR_INTERNAL;
199                         ERROR_DUMP(ret);
200                         goto exit;
201                 }
202
203                 if (ret == YACA_ERROR_NONE)
204                         break;
205
206                 if (BIO_write(dst, tmpbuf, ret) != ret) {
207                         ret = YACA_ERROR_INTERNAL;
208                         ERROR_DUMP(ret);
209                         goto exit;
210                 }
211         }
212
213         BIO_flush(dst);
214
215         /* Check wether the length of the decoded data is what we expected */
216         out_len = BIO_get_mem_data(dst, &out);
217         if (out_len < 0) {
218                 ret = YACA_ERROR_INTERNAL;
219                 ERROR_DUMP(ret);
220                 goto exit;
221         }
222         if ((size_t)out_len != b64_len) {
223                 ret = YACA_ERROR_INVALID_PARAMETER;
224                 goto exit;
225         }
226
227         *output = dst;
228         dst = NULL;
229         ret = YACA_ERROR_NONE;
230
231 exit:
232         BIO_free_all(b64);
233         BIO_free_all(dst);
234
235         return ret;
236 }
237
238 int import_simple(yaca_key_h *key,
239                   yaca_key_type_e key_type,
240                   const char *data,
241                   size_t data_len)
242 {
243         assert(key != NULL);
244         assert(data != NULL);
245         assert(data_len != 0);
246
247         int ret;
248         BIO *decoded = NULL;
249         const char *key_data;
250         size_t key_data_len;
251         struct yaca_key_simple_s *nk = NULL;
252
253         ret = base64_decode(data, data_len, &decoded);
254         if (ret == YACA_ERROR_NONE) {
255                 /* Conversion successfull, get the BASE64 */
256                 long len = BIO_get_mem_data(decoded, &key_data);
257                 if (len <= 0 || key_data == NULL) {
258                         ret = YACA_ERROR_INTERNAL;
259                         ERROR_DUMP(ret);
260                         return ret;
261                 }
262                 key_data_len = len;
263         } else if (ret == YACA_ERROR_INVALID_PARAMETER) {
264                 /* This was not BASE64 or it was corrupted, treat as RAW */
265                 key_data_len = data_len;
266                 key_data = data;
267         } else {
268                 /* Some other, possibly unrecoverable error, give up */
269                 return ret;
270         }
271
272         /* key_bit_len has to fit in size_t */
273         if (key_data_len > SIZE_MAX / 8) {
274                 ret = YACA_ERROR_INVALID_PARAMETER;
275                 goto exit;
276         }
277
278         /* DES key length verification */
279         if (key_type == YACA_KEY_TYPE_DES) {
280                 size_t key_bit_len = key_data_len * 8;
281                 if (key_bit_len != YACA_KEY_LENGTH_UNSAFE_64BIT &&
282                     key_bit_len != YACA_KEY_LENGTH_UNSAFE_128BIT &&
283                     key_bit_len != YACA_KEY_LENGTH_192BIT) {
284                         ret = YACA_ERROR_INVALID_PARAMETER;
285                         goto exit;
286                 }
287         }
288
289         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_data_len, (void**)&nk);
290         if (ret != YACA_ERROR_NONE)
291                 goto exit;
292
293         memcpy(nk->d, key_data, key_data_len);
294         nk->bit_len = key_data_len * 8;
295         nk->key.type = key_type;
296
297         *key = (yaca_key_h)nk;
298         nk = NULL;
299         ret = YACA_ERROR_NONE;
300
301 exit:
302         BIO_free_all(decoded);
303
304         return ret;
305 }
306
307 int import_evp(yaca_key_h *key,
308                yaca_key_type_e key_type,
309                const char *password,
310                const char *data,
311                size_t data_len)
312 {
313         assert(key != NULL);
314         assert(password == NULL || password[0] != '\0');
315         assert(data != NULL);
316         assert(data_len != 0);
317
318         int ret;
319         BIO *src = NULL;
320         EVP_PKEY *pkey = NULL;
321         pem_password_cb *cb = openssl_password_cb;
322         struct openssl_password_data cb_data = {false, password};
323         bool private;
324         bool password_supported;
325         yaca_key_type_e type;
326         struct yaca_key_evp_s *nk = NULL;
327
328         /* Neither PEM nor DER will ever be shorter then 4 bytes (12 seems
329          * to be minimum for DER, much more for PEM). This is just to make
330          * sure we have at least 4 bytes for strncmp() below.
331          */
332         if (data_len < 4)
333                 return YACA_ERROR_INVALID_PARAMETER;
334
335         /* This is because of BIO_new_mem_buf() having its length param typed int */
336         if (data_len > INT_MAX)
337                 return YACA_ERROR_INVALID_PARAMETER;
338
339         src = BIO_new_mem_buf(data, data_len);
340         if (src == NULL) {
341                 ERROR_DUMP(YACA_ERROR_INTERNAL);
342                 return YACA_ERROR_INTERNAL;
343         }
344
345         /* Possible PEM */
346         if (strncmp("----", data, 4) == 0) {
347                 if (pkey == NULL) {
348                         BIO_reset(src);
349                         pkey = PEM_read_bio_PrivateKey(src, NULL, cb, (void*)&cb_data);
350                         if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD)
351                                 return YACA_ERROR_INVALID_PASSWORD;
352                         private = true;
353                         password_supported = true;
354                 }
355
356                 if (pkey == NULL) {
357                         BIO_reset(src);
358                         pkey = PEM_read_bio_PUBKEY(src, NULL, openssl_password_cb_error, NULL);
359                         ERROR_CLEAR();
360                         private = false;
361                         password_supported = false;
362                 }
363
364                 if (pkey == NULL) {
365                         BIO_reset(src);
366                         X509 *x509 = PEM_read_bio_X509(src, NULL, openssl_password_cb_error, NULL);
367                         if (x509 != NULL) {
368                                 pkey = X509_get_pubkey(x509);
369                                 X509_free(x509);
370                         }
371                         ERROR_CLEAR();
372                         private = false;
373                         password_supported = false;
374                 }
375         }
376         /* Possible DER */
377         else {
378                 if (pkey == NULL) {
379                         BIO_reset(src);
380                         pkey = d2i_PKCS8PrivateKey_bio(src, NULL, cb, (void*)&cb_data);
381                         if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD)
382                                 return YACA_ERROR_INVALID_PASSWORD;
383                         private = true;
384                         password_supported = true;
385                 }
386
387                 if (pkey == NULL) {
388                         BIO_reset(src);
389                         pkey = d2i_PrivateKey_bio(src, NULL);
390                         ERROR_CLEAR();
391                         private = true;
392                         password_supported = false;
393                 }
394
395                 if (pkey == NULL) {
396                         BIO_reset(src);
397                         pkey = d2i_PUBKEY_bio(src, NULL);
398                         ERROR_CLEAR();
399                         private = false;
400                         password_supported = false;
401                 }
402
403                 if (pkey == NULL) {
404                         BIO_reset(src);
405                         X509 *x509 = d2i_X509_bio(src, NULL);
406                         if (x509 != NULL) {
407                                 pkey = X509_get_pubkey(x509);
408                                 X509_free(x509);
409                         }
410                         ERROR_CLEAR();
411                         private = false;
412                         password_supported = false;
413                 }
414         }
415
416         BIO_free(src);
417
418         if (pkey == NULL)
419                 return YACA_ERROR_INVALID_PARAMETER;
420
421         /* password was given, but it was not required to perform import */
422         if (password != NULL && !cb_data.password_requested) {
423                 if (password_supported)
424                         ret = YACA_ERROR_INVALID_PASSWORD;
425                 else
426                         ret = YACA_ERROR_INVALID_PARAMETER;
427                 goto exit;
428         }
429
430         switch (EVP_PKEY_type(pkey->type)) {
431         case EVP_PKEY_RSA:
432                 type = private ? YACA_KEY_TYPE_RSA_PRIV : YACA_KEY_TYPE_RSA_PUB;
433                 break;
434
435         case EVP_PKEY_DSA:
436                 type = private ? YACA_KEY_TYPE_DSA_PRIV : YACA_KEY_TYPE_DSA_PUB;
437                 break;
438
439         case EVP_PKEY_EC:
440                 type = private ? YACA_KEY_TYPE_EC_PRIV : YACA_KEY_TYPE_EC_PUB;
441                 break;
442
443         default:
444                 ret = YACA_ERROR_INVALID_PARAMETER;
445                 goto exit;
446         }
447
448         if (type != key_type) {
449                 ret = YACA_ERROR_INVALID_PARAMETER;
450                 goto exit;
451         }
452
453         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
454         if (ret != YACA_ERROR_NONE)
455                 goto exit;
456
457         nk->evp = pkey;
458         *key = (yaca_key_h)nk;
459         (*key)->type = type;
460
461         pkey = NULL;
462         ret = YACA_ERROR_NONE;
463
464 exit:
465         EVP_PKEY_free(pkey);
466
467         return ret;
468 }
469
470 int export_simple_raw(struct yaca_key_simple_s *simple_key,
471                       char **data,
472                       size_t *data_len)
473 {
474         int ret;
475         assert(simple_key != NULL);
476         assert(data != NULL);
477         assert(data_len != NULL);
478
479         size_t key_len = simple_key->bit_len / 8;
480
481         assert(key_len > 0);
482
483         ret = yaca_malloc(key_len, (void**)data);
484         if (ret != YACA_ERROR_NONE)
485                 return ret;
486
487         memcpy(*data, simple_key->d, key_len);
488         *data_len = key_len;
489
490         return YACA_ERROR_NONE;
491 }
492
493 int export_simple_base64(struct yaca_key_simple_s *simple_key,
494                          char **data,
495                          size_t *data_len)
496 {
497         assert(simple_key != NULL);
498         assert(data != NULL);
499         assert(data_len != NULL);
500
501         int ret;
502         size_t key_len = simple_key->bit_len / 8;
503         BIO *b64;
504         BIO *mem;
505         char *bio_data;
506         long bio_data_len;
507
508         b64 = BIO_new(BIO_f_base64());
509         if (b64 == NULL) {
510                 ret = YACA_ERROR_INTERNAL;
511                 ERROR_DUMP(ret);
512                 return ret;
513         }
514
515         mem = BIO_new(BIO_s_mem());
516         if (mem == NULL) {
517                 ret = YACA_ERROR_INTERNAL;
518                 ERROR_DUMP(ret);
519                 goto exit;
520         }
521
522         BIO_push(b64, mem);
523         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
524
525         ret = BIO_write(b64, simple_key->d, key_len);
526         if (ret <= 0 || (unsigned)ret != key_len) {
527                 ret = YACA_ERROR_INTERNAL;
528                 ERROR_DUMP(ret);
529                 goto exit;
530         }
531
532         ret = BIO_flush(b64);
533         if (ret <= 0) {
534                 ret = YACA_ERROR_INTERNAL;
535                 ERROR_DUMP(ret);
536                 goto exit;
537         }
538
539         bio_data_len = BIO_get_mem_data(mem, &bio_data);
540         if (bio_data_len <= 0) {
541                 ret = YACA_ERROR_INTERNAL;
542                 ERROR_DUMP(ret);
543                 goto exit;
544         }
545
546         ret = yaca_malloc(bio_data_len, (void**)data);
547         if (ret != YACA_ERROR_NONE)
548                 goto exit;
549
550         memcpy(*data, bio_data, bio_data_len);
551         *data_len = bio_data_len;
552         ret = YACA_ERROR_NONE;
553
554 exit:
555         BIO_free_all(b64);
556
557         return ret;
558 }
559
560 int export_evp_default_bio(struct yaca_key_evp_s *evp_key,
561                            yaca_key_file_format_e key_file_fmt,
562                            const char *password,
563                            BIO *mem)
564 {
565         assert(evp_key != NULL);
566         assert(password == NULL || password[0] != '\0');
567         assert(mem != NULL);
568
569         int ret;
570         const EVP_CIPHER *enc = NULL;
571
572         if (password != NULL)
573                 enc = EVP_aes_256_cbc();
574
575         switch (key_file_fmt) {
576
577         case YACA_KEY_FILE_FORMAT_PEM:
578                 switch (evp_key->key.type) {
579
580                 case YACA_KEY_TYPE_RSA_PRIV:
581                         ret = PEM_write_bio_RSAPrivateKey(mem, EVP_PKEY_get0(evp_key->evp),
582                                                           enc, NULL, 0, NULL, (void*)password);
583                         break;
584                 case YACA_KEY_TYPE_DSA_PRIV:
585                         ret = PEM_write_bio_DSAPrivateKey(mem, EVP_PKEY_get0(evp_key->evp),
586                                                           enc, NULL, 0, NULL, (void*)password);
587                         break;
588
589                 case YACA_KEY_TYPE_RSA_PUB:
590                 case YACA_KEY_TYPE_DSA_PUB:
591                         if (password != NULL)
592                                 return YACA_ERROR_INVALID_PARAMETER;
593                         ret = PEM_write_bio_PUBKEY(mem, evp_key->evp);
594                         break;
595
596                 case YACA_KEY_TYPE_DH_PRIV:
597                 case YACA_KEY_TYPE_DH_PUB:
598                 case YACA_KEY_TYPE_EC_PRIV:
599                 case YACA_KEY_TYPE_EC_PUB:
600                         //TODO NOT_IMPLEMENTED
601                 default:
602                         return YACA_ERROR_INVALID_PARAMETER;
603                 }
604
605                 break;
606
607         case YACA_KEY_FILE_FORMAT_DER:
608                 switch (evp_key->key.type) {
609
610                 case YACA_KEY_TYPE_RSA_PRIV:
611                         if (password != NULL)
612                                 return YACA_ERROR_INVALID_PARAMETER;
613                         ret = i2d_RSAPrivateKey_bio(mem, EVP_PKEY_get0(evp_key->evp));
614                         break;
615
616                 case YACA_KEY_TYPE_DSA_PRIV:
617                         if (password != NULL)
618                                 return YACA_ERROR_INVALID_PARAMETER;
619                         ret = i2d_DSAPrivateKey_bio(mem, EVP_PKEY_get0(evp_key->evp));
620                         break;
621
622                 case YACA_KEY_TYPE_RSA_PUB:
623                 case YACA_KEY_TYPE_DSA_PUB:
624                         if (password != NULL)
625                                 return YACA_ERROR_INVALID_PARAMETER;
626                         ret = i2d_PUBKEY_bio(mem, evp_key->evp);
627                         break;
628
629                 case YACA_KEY_TYPE_DH_PRIV:
630                 case YACA_KEY_TYPE_DH_PUB:
631                 case YACA_KEY_TYPE_EC_PRIV:
632                 case YACA_KEY_TYPE_EC_PUB:
633                         //TODO NOT_IMPLEMENTED
634                 default:
635                         return YACA_ERROR_INVALID_PARAMETER;
636                 }
637
638                 break;
639
640         default:
641                 return YACA_ERROR_INVALID_PARAMETER;
642         }
643
644         if (ret <= 0) {
645                 ret = YACA_ERROR_INTERNAL;
646                 ERROR_DUMP(ret);
647                 return ret;
648         }
649
650         return YACA_ERROR_NONE;
651 }
652
653 int export_evp_pkcs8_bio(struct yaca_key_evp_s *evp_key,
654                          yaca_key_file_format_e key_file_fmt,
655                          const char *password,
656                          BIO *mem)
657 {
658         assert(evp_key != NULL);
659         assert(password == NULL || password[0] != '\0');
660         assert(mem != NULL);
661
662         int ret;
663         int nid = NID_pbeWithMD5AndDES_CBC;
664
665         /* PKCS8 export requires a password */
666         if (password == NULL)
667                 return YACA_ERROR_INVALID_PARAMETER;
668
669         switch (key_file_fmt) {
670
671         case YACA_KEY_FILE_FORMAT_PEM:
672                 switch (evp_key->key.type) {
673
674                 case YACA_KEY_TYPE_RSA_PRIV:
675                 case YACA_KEY_TYPE_DSA_PRIV:
676                         ret = PEM_write_bio_PKCS8PrivateKey_nid(mem, evp_key->evp, nid,
677                                                                 NULL, 0, NULL, (void*)password);
678                         break;
679                 case YACA_KEY_TYPE_DH_PRIV:
680                 case YACA_KEY_TYPE_EC_PRIV:
681                         //TODO NOT_IMPLEMENTED
682                 default:
683                         /* Public keys are not supported by PKCS8 */
684                         return YACA_ERROR_INVALID_PARAMETER;
685                 }
686
687                 break;
688
689         case YACA_KEY_FILE_FORMAT_DER:
690                 switch (evp_key->key.type) {
691
692                 case YACA_KEY_TYPE_RSA_PRIV:
693                 case YACA_KEY_TYPE_DSA_PRIV:
694                         ret = i2d_PKCS8PrivateKey_nid_bio(mem, evp_key->evp, nid,
695                                                           NULL, 0, NULL, (void*)password);
696                         break;
697
698                 case YACA_KEY_TYPE_DH_PRIV:
699                 case YACA_KEY_TYPE_EC_PRIV:
700                         //TODO NOT_IMPLEMENTED
701                 default:
702                         /* Public keys are not supported by PKCS8 */
703                         return YACA_ERROR_INVALID_PARAMETER;
704                 }
705
706                 break;
707
708         default:
709                 return YACA_ERROR_INVALID_PARAMETER;
710         }
711
712         if (ret <= 0) {
713                 ret = YACA_ERROR_INTERNAL;
714                 ERROR_DUMP(ret);
715                 return ret;
716         }
717
718         return YACA_ERROR_NONE;
719 }
720
721 int export_evp(struct yaca_key_evp_s *evp_key,
722                yaca_key_format_e key_fmt,
723                yaca_key_file_format_e key_file_fmt,
724                const char *password,
725                char **data,
726                size_t *data_len)
727 {
728         assert(evp_key != NULL);
729         assert(password == NULL || password[0] != '\0');
730         assert(data != NULL);
731         assert(data_len != NULL);
732
733         int ret = YACA_ERROR_NONE;
734         BIO *mem;
735         char *bio_data;
736         long bio_data_len;
737
738         mem = BIO_new(BIO_s_mem());
739         if (mem == NULL) {
740                 ret = YACA_ERROR_INTERNAL;
741                 ERROR_DUMP(ret);
742                 return ret;
743         }
744
745         switch (key_fmt) {
746         case YACA_KEY_FORMAT_DEFAULT:
747                 ret = export_evp_default_bio(evp_key, key_file_fmt, password, mem);
748                 break;
749         case YACA_KEY_FORMAT_PKCS8:
750                 ret = export_evp_pkcs8_bio(evp_key, key_file_fmt, password, mem);
751                 break;
752         default:
753                 ret = YACA_ERROR_INVALID_PARAMETER;
754                 break;
755         }
756
757         if (ret != YACA_ERROR_NONE)
758                 goto exit;
759
760         ret = BIO_flush(mem);
761         if (ret <= 0) {
762                 ret = YACA_ERROR_INTERNAL;
763                 ERROR_DUMP(ret);
764                 goto exit;
765         }
766
767         bio_data_len = BIO_get_mem_data(mem, &bio_data);
768         if (bio_data_len <= 0) {
769                 ret = YACA_ERROR_INTERNAL;
770                 ERROR_DUMP(ret);
771                 goto exit;
772         }
773
774         ret = yaca_malloc(bio_data_len, (void**)data);
775         if (ret != YACA_ERROR_NONE)
776                 goto exit;
777
778         memcpy(*data, bio_data, bio_data_len);
779         *data_len = bio_data_len;
780         ret = YACA_ERROR_NONE;
781
782 exit:
783         BIO_free_all(mem);
784
785         return ret;
786 }
787
788 int generate_simple(struct yaca_key_simple_s **out, size_t key_bit_len)
789 {
790         assert(out != NULL);
791
792         if (key_bit_len % 8 != 0)
793                 return YACA_ERROR_INVALID_PARAMETER;
794
795         int ret;
796         struct yaca_key_simple_s *nk;
797         size_t key_byte_len = key_bit_len / 8;
798
799         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
800         if (ret != YACA_ERROR_NONE)
801                 return ret;
802
803         nk->bit_len = key_bit_len;
804
805         ret = yaca_randomize_bytes(nk->d, key_byte_len);
806         if (ret != YACA_ERROR_NONE)
807                 return ret;
808
809         *out = nk;
810         return YACA_ERROR_NONE;
811 }
812
813 int generate_simple_des(struct yaca_key_simple_s **out, size_t key_bit_len)
814 {
815         assert(out != NULL);
816
817         if (key_bit_len != YACA_KEY_LENGTH_UNSAFE_64BIT &&
818             key_bit_len != YACA_KEY_LENGTH_UNSAFE_128BIT &&
819             key_bit_len != YACA_KEY_LENGTH_192BIT)
820                 return YACA_ERROR_INVALID_PARAMETER;
821
822         int ret;
823         struct yaca_key_simple_s *nk;
824         size_t key_byte_len = key_bit_len / 8;
825
826         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
827         if (ret != YACA_ERROR_NONE)
828                 return ret;
829
830         DES_cblock *des_key = (DES_cblock*)nk->d;
831         if (key_byte_len >= 8) {
832                 ret = DES_random_key(des_key);
833                 if (ret != 1) {
834                         ret = YACA_ERROR_INTERNAL;
835                         ERROR_DUMP(ret);
836                         goto exit;
837                 }
838         }
839         if (key_byte_len >= 16) {
840                 ret = DES_random_key(des_key + 1);
841                 if (ret != 1) {
842                         ret = YACA_ERROR_INTERNAL;
843                         ERROR_DUMP(ret);
844                         goto exit;
845                 }
846         }
847         if (key_byte_len >= 24) {
848                 ret = DES_random_key(des_key + 2);
849                 if (ret != 1) {
850                         ret = YACA_ERROR_INTERNAL;
851                         ERROR_DUMP(ret);
852                         goto exit;
853                 }
854         }
855
856         nk->bit_len = key_bit_len;
857         *out = nk;
858         nk = NULL;
859         ret = YACA_ERROR_NONE;
860
861 exit:
862         yaca_free(nk);
863
864         return ret;
865 }
866
867 static int generate_evp_pkey_params(int evp_id, size_t key_bit_len, EVP_PKEY **params)
868 {
869         assert(key_bit_len > 0);
870         assert(params != NULL);
871
872         int ret;
873         EVP_PKEY_CTX *pctx = NULL;
874         int bit_len = 0;
875         int dh_prime_len = 0;
876         int dh_generator = 0;
877         int dh_rfc5114 = 0;
878         int ec_nid = 0;
879
880         switch (evp_id) {
881         case EVP_PKEY_DSA:
882                 if ((key_bit_len & YACA_INTERNAL_KEYLEN_TYPE_MASK) != YACA_INTERNAL_KEYLEN_TYPE_BITS ||
883                     key_bit_len > INT_MAX || key_bit_len < 512 || key_bit_len % 64 != 0)
884                         return YACA_ERROR_INVALID_PARAMETER;
885
886                 bit_len = key_bit_len;
887
888                 break;
889         case EVP_PKEY_DH:
890                 if ((key_bit_len & YACA_INTERNAL_KEYLEN_TYPE_MASK) == YACA_INTERNAL_KEYLEN_TYPE_DH) {
891                         size_t gen_block = key_bit_len & YACA_INTERNAL_KEYLEN_DH_GEN_MASK;
892                         size_t prime_len_block = key_bit_len & YACA_INTERNAL_KEYLEN_DH_PRIME_MASK;
893
894                         /* This is impossible now as we take only 16 bits,
895                          * but for the sake of type safety */
896                         if (prime_len_block > INT_MAX)
897                                 return YACA_ERROR_INVALID_PARAMETER;
898                         dh_prime_len = prime_len_block;
899
900                         if (gen_block == YACA_INTERNAL_KEYLEN_DH_GEN_2)
901                                 dh_generator = 2;
902                         else if (gen_block == YACA_INTERNAL_KEYLEN_DH_GEN_5)
903                                 dh_generator = 5;
904                         else
905                                 return YACA_ERROR_INVALID_PARAMETER;
906
907                 } else if ((key_bit_len & YACA_INTERNAL_KEYLEN_TYPE_MASK) == YACA_INTERNAL_KEYLEN_TYPE_DH_RFC) {
908                         if (key_bit_len == YACA_KEY_LENGTH_DH_RFC_1024_160)
909                                 dh_rfc5114 = 1; /* OpenSSL magic numbers */
910                         else if (key_bit_len == YACA_KEY_LENGTH_DH_RFC_2048_224)
911                                 dh_rfc5114 = 2;
912                         else if (key_bit_len == YACA_KEY_LENGTH_DH_RFC_2048_256)
913                                 dh_rfc5114 = 3;
914                         else
915                                 return YACA_ERROR_INVALID_PARAMETER;
916
917                 } else {
918                         return YACA_ERROR_INVALID_PARAMETER;
919                 }
920
921                 break;
922         case EVP_PKEY_EC:
923                 ret = convert_ec_to_nid(key_bit_len, &ec_nid);
924                 if (ret != YACA_ERROR_NONE)
925                         return ret;
926
927                 break;
928         default:
929                 /* We shouldn't be here */
930                 assert(false);
931                 return YACA_ERROR_INTERNAL;
932         }
933
934         pctx = EVP_PKEY_CTX_new_id(evp_id, NULL);
935         if (pctx == NULL) {
936                 ret = YACA_ERROR_INTERNAL;
937                 ERROR_DUMP(ret);
938                 goto exit;
939         }
940
941         ret = EVP_PKEY_paramgen_init(pctx);
942         if (ret != 1) {
943                 ret = YACA_ERROR_INTERNAL;
944                 ERROR_DUMP(ret);
945                 goto exit;
946         }
947
948         switch (evp_id) {
949         case EVP_PKEY_DSA:
950                 ret = EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, bit_len);
951                 break;
952         case EVP_PKEY_DH:
953                 if (dh_rfc5114 > 0) {
954                         /* The following code is based on the macro call below.
955                          * Unfortunately it doesn't work and the suspected reason is the
956                          * fact that the _set_dh_ variant actually passes EVP_PKEY_DHX:
957                          * ret = EVP_PKEY_CTX_set_dh_rfc5114(pctx, dh_rfc5114); */
958                         ret = EVP_PKEY_CTX_ctrl(pctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
959                                                 EVP_PKEY_CTRL_DH_RFC5114, dh_rfc5114, NULL);
960                 } else {
961                         ret = EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, dh_prime_len);
962                         if (ret == 1)
963                                 ret = EVP_PKEY_CTX_set_dh_paramgen_generator(pctx, dh_generator);
964                 }
965                 break;
966         case EVP_PKEY_EC:
967                 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ec_nid);
968                 if (ret == 1)
969                         ret = EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE);
970                 break;
971         }
972         if (ret != 1) {
973                 ret = YACA_ERROR_INTERNAL;
974                 ERROR_DUMP(ret);
975                 goto exit;
976         }
977
978         ret = EVP_PKEY_paramgen(pctx, params);
979         if (ret != 1 || params == NULL) {
980                 ret = YACA_ERROR_INTERNAL;
981                 ERROR_DUMP(ret);
982                 goto exit;
983         }
984
985         ret = YACA_ERROR_NONE;
986
987 exit:
988         EVP_PKEY_CTX_free(pctx);
989         return ret;
990 }
991
992 static int generate_evp_pkey_key(int evp_id, size_t key_bit_len, EVP_PKEY *params, EVP_PKEY **key)
993 {
994         assert(key != NULL);
995         assert(key_bit_len > 0 || params != NULL);
996
997         int ret;
998         EVP_PKEY_CTX *kctx = NULL;
999
1000         switch (evp_id) {
1001         case EVP_PKEY_RSA:
1002                 assert(params == NULL);
1003                 kctx = EVP_PKEY_CTX_new_id(evp_id, NULL);
1004                 break;
1005         case EVP_PKEY_DSA:
1006         case EVP_PKEY_DH:
1007         case EVP_PKEY_EC:
1008                 if (params == NULL) {
1009                         ret = generate_evp_pkey_params(evp_id, key_bit_len, &params);
1010                         if (ret != YACA_ERROR_NONE)
1011                                 return ret;
1012                 } else {
1013                         CRYPTO_add(&params->references, 1, CRYPTO_LOCK_EVP_PKEY);
1014                 }
1015
1016                 kctx = EVP_PKEY_CTX_new(params, NULL);
1017                 break;
1018         default:
1019                 assert(false);
1020                 return YACA_ERROR_INTERNAL;
1021         }
1022         if (kctx == NULL) {
1023                 ret = YACA_ERROR_INTERNAL;
1024                 ERROR_DUMP(ret);
1025                 goto exit;
1026         }
1027
1028         ret = EVP_PKEY_keygen_init(kctx);
1029         if (ret != 1) {
1030                 ret = YACA_ERROR_INTERNAL;
1031                 ERROR_DUMP(ret);
1032                 goto exit;
1033         }
1034
1035         if (evp_id == EVP_PKEY_RSA) {
1036                 if ((key_bit_len & YACA_INTERNAL_KEYLEN_TYPE_MASK) != YACA_INTERNAL_KEYLEN_TYPE_BITS ||
1037                     key_bit_len > INT_MAX || key_bit_len % 8 != 0) {
1038                         ret = YACA_ERROR_INVALID_PARAMETER;
1039                         goto exit;
1040                 }
1041
1042                 ret = EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, (int)key_bit_len);
1043                 if (ret != 1) {
1044                         ret = ERROR_HANDLE();
1045                         goto exit;
1046                 }
1047         }
1048
1049         ret = EVP_PKEY_keygen(kctx, key);
1050         if (ret != 1 || key == NULL) {
1051                 ret = YACA_ERROR_INTERNAL;
1052                 ERROR_DUMP(ret);
1053                 goto exit;
1054         }
1055
1056         ret = YACA_ERROR_NONE;
1057
1058 exit:
1059         EVP_PKEY_CTX_free(kctx);
1060         EVP_PKEY_free(params);
1061         return ret;
1062 }
1063
1064 static int generate_evp(yaca_key_type_e out_type, size_t key_bit_len,
1065                         struct yaca_key_evp_s *params, struct yaca_key_evp_s **out)
1066 {
1067         assert(out != NULL);
1068         assert(key_bit_len > 0 || params != NULL);
1069
1070         int ret;
1071         int evp_id;
1072         EVP_PKEY *pkey_out = NULL;
1073         EVP_PKEY *pkey_params = NULL;
1074
1075         if (params != NULL) {
1076                 yaca_key_type_e key_type;
1077                 yaca_key_type_e params_type = params->key.type;
1078
1079                 ret = convert_params_to_priv(params_type, &key_type);
1080                 if (ret != YACA_ERROR_NONE)
1081                         return ret;
1082
1083                 if (out_type != key_type)
1084                         return YACA_ERROR_INVALID_PARAMETER;
1085
1086                 pkey_params = params->evp;
1087         }
1088
1089         switch (out_type) {
1090         case YACA_KEY_TYPE_DSA_PARAMS:
1091         case YACA_KEY_TYPE_DH_PARAMS:
1092         case YACA_KEY_TYPE_EC_PARAMS:
1093                 assert(params == NULL);
1094                 ret = convert_params_to_evp_id(out_type, &evp_id);
1095                 if (ret != YACA_ERROR_NONE)
1096                         return ret;
1097
1098                 ret = generate_evp_pkey_params(evp_id, key_bit_len, &pkey_out);
1099                 break;
1100         case YACA_KEY_TYPE_RSA_PRIV:
1101         case YACA_KEY_TYPE_DSA_PRIV:
1102         case YACA_KEY_TYPE_DH_PRIV:
1103         case YACA_KEY_TYPE_EC_PRIV:
1104                 ret = convert_priv_to_evp_id(out_type, &evp_id);
1105                 if (ret != YACA_ERROR_NONE)
1106                         return ret;
1107
1108                 ret = generate_evp_pkey_key(evp_id, key_bit_len, pkey_params, &pkey_out);
1109                 break;
1110         default:
1111                 return YACA_ERROR_INVALID_PARAMETER;
1112         }
1113         if (ret != YACA_ERROR_NONE)
1114                 return ret;
1115
1116         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)out);
1117         if (ret != YACA_ERROR_NONE)
1118                 goto exit;
1119
1120         (*out)->evp = pkey_out;
1121         pkey_out = NULL;
1122
1123         ret = YACA_ERROR_NONE;
1124
1125 exit:
1126         EVP_PKEY_free(pkey_out);
1127         return ret;
1128 }
1129
1130 struct yaca_key_simple_s *key_get_simple(const yaca_key_h key)
1131 {
1132         struct yaca_key_simple_s *k;
1133
1134         if (key == YACA_KEY_NULL)
1135                 return NULL;
1136
1137         switch (key->type) {
1138         case YACA_KEY_TYPE_SYMMETRIC:
1139         case YACA_KEY_TYPE_DES:
1140         case YACA_KEY_TYPE_IV:
1141                 k = (struct yaca_key_simple_s *)key;
1142
1143                 /* sanity check */
1144                 assert(k->bit_len != 0);
1145                 assert(k->bit_len % 8 == 0);
1146                 assert(k->d != NULL);
1147
1148                 return k;
1149         default:
1150                 return NULL;
1151         }
1152 }
1153
1154 struct yaca_key_evp_s *key_get_evp(const yaca_key_h key)
1155 {
1156         struct yaca_key_evp_s *k;
1157
1158         if (key == YACA_KEY_NULL)
1159                 return NULL;
1160
1161         switch (key->type) {
1162         case YACA_KEY_TYPE_RSA_PUB:
1163         case YACA_KEY_TYPE_RSA_PRIV:
1164         case YACA_KEY_TYPE_DSA_PUB:
1165         case YACA_KEY_TYPE_DSA_PRIV:
1166         case YACA_KEY_TYPE_DSA_PARAMS:
1167         case YACA_KEY_TYPE_DH_PUB:
1168         case YACA_KEY_TYPE_DH_PRIV:
1169         case YACA_KEY_TYPE_DH_PARAMS:
1170         case YACA_KEY_TYPE_EC_PUB:
1171         case YACA_KEY_TYPE_EC_PRIV:
1172         case YACA_KEY_TYPE_EC_PARAMS:
1173                 k = (struct yaca_key_evp_s *)key;
1174
1175                 /* sanity check */
1176                 assert(k->evp != NULL);
1177
1178                 return k;
1179         default:
1180                 return NULL;
1181         }
1182 }
1183
1184 static yaca_key_h key_copy_simple(const struct yaca_key_simple_s *key)
1185 {
1186         int ret;
1187         assert(key != NULL);
1188
1189         struct yaca_key_simple_s *copy;
1190         size_t size = sizeof(struct yaca_key_simple_s) + key->bit_len / 8;
1191
1192         ret = yaca_zalloc(size, (void**)&copy);
1193         if (ret != YACA_ERROR_NONE)
1194                 return YACA_KEY_NULL;
1195
1196         memcpy(copy, key, size);
1197         return (yaca_key_h)copy;
1198 }
1199
1200 static yaca_key_h key_copy_evp(const struct yaca_key_evp_s *key)
1201 {
1202         int ret;
1203         assert(key != NULL);
1204
1205         struct yaca_key_evp_s *copy = NULL;
1206         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&copy);
1207         if (ret != YACA_ERROR_NONE)
1208                 return YACA_KEY_NULL;
1209
1210         /* raise the refcount */
1211         CRYPTO_add(&key->evp->references, 1, CRYPTO_LOCK_EVP_PKEY);
1212
1213         copy->key.type = key->key.type;
1214         copy->evp = key->evp;
1215         return (yaca_key_h)copy;
1216 }
1217
1218 yaca_key_h key_copy(const yaca_key_h key)
1219 {
1220         struct yaca_key_simple_s *simple = key_get_simple(key);
1221         struct yaca_key_evp_s *evp = key_get_evp(key);
1222
1223         if (simple != NULL)
1224                 return key_copy_simple(simple);
1225         else if (evp != NULL)
1226                 return key_copy_evp(evp);
1227
1228         return YACA_KEY_NULL;
1229 }
1230
1231 API int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type)
1232 {
1233         const struct yaca_key_s *lkey = (const struct yaca_key_s *)key;
1234
1235         if (lkey == NULL || key_type == NULL)
1236                 return YACA_ERROR_INVALID_PARAMETER;
1237
1238         *key_type = lkey->type;
1239         return YACA_ERROR_NONE;
1240 }
1241
1242 API int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len)
1243 {
1244         const struct yaca_key_simple_s *simple_key = key_get_simple(key);
1245         const struct yaca_key_evp_s *evp_key = key_get_evp(key);
1246
1247         if (key_bit_len == NULL)
1248                 return YACA_ERROR_INVALID_PARAMETER;
1249
1250         if (simple_key != NULL) {
1251                 *key_bit_len = simple_key->bit_len;
1252                 return YACA_ERROR_NONE;
1253         }
1254
1255         if (evp_key != NULL) {
1256                 int ret;
1257
1258                 switch (evp_key->key.type) {
1259                 case YACA_KEY_TYPE_RSA_PRIV:
1260                 case YACA_KEY_TYPE_RSA_PUB:
1261                 case YACA_KEY_TYPE_DSA_PRIV:
1262                 case YACA_KEY_TYPE_DSA_PUB:
1263                 case YACA_KEY_TYPE_DH_PRIV:
1264                 case YACA_KEY_TYPE_DH_PUB:
1265                         ret = EVP_PKEY_bits(evp_key->evp);
1266                         if (ret <= 0) {
1267                                 ret = YACA_ERROR_INTERNAL;
1268                                 ERROR_DUMP(ret);
1269                                 return ret;
1270                         }
1271
1272                         *key_bit_len = ret;
1273                         return YACA_ERROR_NONE;
1274                 case YACA_KEY_TYPE_EC_PRIV:
1275                 case YACA_KEY_TYPE_EC_PUB: {
1276                         assert(EVP_PKEY_type(evp_key->evp->type) == EVP_PKEY_EC);
1277
1278                         const EC_KEY *eck = EVP_PKEY_get0(evp_key->evp);
1279                         const EC_GROUP *ecg = EC_KEY_get0_group(eck);
1280                         int flags = EC_GROUP_get_asn1_flag(ecg);
1281                         int nid;
1282
1283                         if (!(flags & OPENSSL_EC_NAMED_CURVE))
1284                                 /* This is case of a custom (not named) curve, that can happen when someone
1285                                    imports such a key into YACA. There is nothing that can be returned here */
1286                                 return YACA_ERROR_INVALID_PARAMETER;
1287
1288                         nid = EC_GROUP_get_curve_name(ecg);
1289                         return convert_nid_to_ec(nid, key_bit_len);
1290                 }
1291                 default:
1292                         /* We shouldn't be here */
1293                         assert(false);
1294                         return YACA_ERROR_INTERNAL;
1295                 }
1296         }
1297
1298         return YACA_ERROR_INVALID_PARAMETER;
1299 }
1300
1301 API int yaca_key_import(yaca_key_type_e key_type,
1302                         const char *password,
1303                         const char *data,
1304                         size_t data_len,
1305                         yaca_key_h *key)
1306 {
1307         if (key == NULL || data == NULL || data_len == 0)
1308                 return YACA_ERROR_INVALID_PARAMETER;
1309
1310         /* allow an empty password, OpenSSL returns an error with "" */
1311         if (password != NULL && password[0] == '\0')
1312                 password = NULL;
1313
1314         switch (key_type) {
1315         case YACA_KEY_TYPE_SYMMETRIC:
1316         case YACA_KEY_TYPE_DES:
1317         case YACA_KEY_TYPE_IV:
1318                 if (password != NULL)
1319                         return YACA_ERROR_INVALID_PARAMETER;
1320                 return import_simple(key, key_type, data, data_len);
1321         case YACA_KEY_TYPE_RSA_PUB:
1322         case YACA_KEY_TYPE_RSA_PRIV:
1323         case YACA_KEY_TYPE_DSA_PUB:
1324         case YACA_KEY_TYPE_DSA_PRIV:
1325                 return import_evp(key, key_type, password, data, data_len);
1326         case YACA_KEY_TYPE_DH_PUB:
1327         case YACA_KEY_TYPE_DH_PRIV:
1328         case YACA_KEY_TYPE_EC_PUB:
1329         case YACA_KEY_TYPE_EC_PRIV:
1330                 //TODO NOT_IMPLEMENTED
1331         default:
1332                 return YACA_ERROR_INVALID_PARAMETER;
1333         }
1334 }
1335
1336 API int yaca_key_export(const yaca_key_h key,
1337                         yaca_key_format_e key_fmt,
1338                         yaca_key_file_format_e key_file_fmt,
1339                         const char *password,
1340                         char **data,
1341                         size_t *data_len)
1342 {
1343         struct yaca_key_simple_s *simple_key = key_get_simple(key);
1344         struct yaca_key_evp_s *evp_key = key_get_evp(key);
1345
1346         if (data == NULL || data_len == NULL)
1347                 return YACA_ERROR_INVALID_PARAMETER;
1348
1349         /* allow an empty password, OpenSSL returns an error with "" */
1350         if (password != NULL && password[0] == '\0')
1351                 password = NULL;
1352
1353         if (password != NULL && simple_key != NULL)
1354                 return YACA_ERROR_INVALID_PARAMETER;
1355
1356         if (key_fmt == YACA_KEY_FORMAT_DEFAULT &&
1357             key_file_fmt == YACA_KEY_FILE_FORMAT_RAW &&
1358             simple_key != NULL)
1359                 return export_simple_raw(simple_key, data, data_len);
1360
1361         if (key_fmt == YACA_KEY_FORMAT_DEFAULT &&
1362             key_file_fmt == YACA_KEY_FILE_FORMAT_BASE64 &&
1363             simple_key != NULL)
1364                 return export_simple_base64(simple_key, data, data_len);
1365
1366         if (evp_key != NULL)
1367                 return export_evp(evp_key, key_fmt, key_file_fmt,
1368                                   password, data, data_len);
1369
1370         return YACA_ERROR_INVALID_PARAMETER;
1371 }
1372
1373 API int yaca_key_generate(yaca_key_type_e key_type,
1374                           size_t key_bit_len,
1375                           yaca_key_h *key)
1376 {
1377         int ret;
1378         struct yaca_key_simple_s *nk_simple = NULL;
1379         struct yaca_key_evp_s *nk_evp = NULL;
1380
1381         if (key == NULL || key_bit_len == 0)
1382                 return YACA_ERROR_INVALID_PARAMETER;
1383
1384         switch (key_type) {
1385         case YACA_KEY_TYPE_SYMMETRIC:
1386         case YACA_KEY_TYPE_IV:
1387                 ret = generate_simple(&nk_simple, key_bit_len);
1388                 break;
1389         case YACA_KEY_TYPE_DES:
1390                 ret = generate_simple_des(&nk_simple, key_bit_len);
1391                 break;
1392         case YACA_KEY_TYPE_RSA_PRIV:
1393         case YACA_KEY_TYPE_DSA_PRIV:
1394         case YACA_KEY_TYPE_DSA_PARAMS:
1395         case YACA_KEY_TYPE_DH_PRIV:
1396         case YACA_KEY_TYPE_DH_PARAMS:
1397         case YACA_KEY_TYPE_EC_PRIV:
1398         case YACA_KEY_TYPE_EC_PARAMS:
1399                 ret = generate_evp(key_type, key_bit_len, NULL, &nk_evp);
1400                 break;
1401         default:
1402                 return YACA_ERROR_INVALID_PARAMETER;
1403         }
1404
1405         if (ret != YACA_ERROR_NONE)
1406                 return ret;
1407
1408         if (nk_simple != NULL) {
1409                 nk_simple->key.type = key_type;
1410                 *key = (yaca_key_h)nk_simple;
1411         } else if (nk_evp != NULL) {
1412                 nk_evp->key.type = key_type;
1413                 *key = (yaca_key_h)nk_evp;
1414         } else {
1415                 assert(false);
1416         }
1417
1418         return YACA_ERROR_NONE;
1419 }
1420
1421 API int yaca_key_generate_from_parameters(const yaca_key_h params, yaca_key_h *prv_key)
1422 {
1423         int ret;
1424         struct yaca_key_evp_s *evp_params = key_get_evp(params);
1425         yaca_key_type_e params_type;
1426         yaca_key_type_e key_type;
1427         struct yaca_key_evp_s *nk_evp = NULL;
1428
1429         if (evp_params == NULL || prv_key == NULL)
1430                 return YACA_ERROR_INVALID_PARAMETER;
1431
1432         ret = yaca_key_get_type(params, &params_type);
1433         if (ret != YACA_ERROR_NONE)
1434                 return ret;
1435
1436         ret = convert_params_to_priv(params_type, &key_type);
1437         if (ret != YACA_ERROR_NONE)
1438                 return ret;
1439
1440         ret = generate_evp(key_type, 0, evp_params, &nk_evp);
1441         if (ret != YACA_ERROR_NONE)
1442                 return ret;
1443
1444         assert(nk_evp != NULL);
1445
1446         nk_evp->key.type = key_type;
1447         *prv_key = (yaca_key_h)nk_evp;
1448
1449         return YACA_ERROR_NONE;
1450 }
1451
1452 API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key)
1453 {
1454         int ret;
1455         struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
1456         struct yaca_key_evp_s *nk;
1457         BIO *mem = NULL;
1458         EVP_PKEY *pkey = NULL;
1459
1460         if (prv_key == YACA_KEY_NULL || evp_key == NULL || pub_key == NULL)
1461                 return YACA_ERROR_INVALID_PARAMETER;
1462
1463         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
1464         if (ret != YACA_ERROR_NONE)
1465                 return ret;
1466
1467         mem = BIO_new(BIO_s_mem());
1468         if (mem == NULL) {
1469                 ret = YACA_ERROR_INTERNAL;
1470                 ERROR_DUMP(ret);
1471                 goto exit;
1472         }
1473
1474         ret = i2d_PUBKEY_bio(mem, evp_key->evp);
1475         if (ret != 1) {
1476                 ret = YACA_ERROR_INTERNAL;
1477                 ERROR_DUMP(ret);
1478                 goto exit;
1479         }
1480
1481         pkey = d2i_PUBKEY_bio(mem, NULL);
1482         if (pkey == NULL) {
1483                 ret = YACA_ERROR_INTERNAL;
1484                 ERROR_DUMP(ret);
1485                 goto exit;
1486         }
1487
1488         BIO_free(mem);
1489         mem = NULL;
1490
1491         switch (prv_key->type) {
1492         case YACA_KEY_TYPE_RSA_PRIV:
1493                 nk->key.type = YACA_KEY_TYPE_RSA_PUB;
1494                 break;
1495         case YACA_KEY_TYPE_DSA_PRIV:
1496                 nk->key.type = YACA_KEY_TYPE_DSA_PUB;
1497                 break;
1498         case YACA_KEY_TYPE_DH_PRIV:
1499                 nk->key.type = YACA_KEY_TYPE_DH_PUB;
1500                 break;
1501         case YACA_KEY_TYPE_EC_PRIV:
1502                 nk->key.type = YACA_KEY_TYPE_EC_PUB;
1503                 break;
1504         default:
1505                 ret = YACA_ERROR_INVALID_PARAMETER;
1506                 goto exit;
1507         }
1508
1509         nk->evp = pkey;
1510         pkey = NULL;
1511         *pub_key = (yaca_key_h)nk;
1512         nk = NULL;
1513         ret = YACA_ERROR_NONE;
1514
1515 exit:
1516         EVP_PKEY_free(pkey);
1517         BIO_free(mem);
1518         yaca_free(nk);
1519
1520         return ret;
1521 }
1522
1523 API void yaca_key_destroy(yaca_key_h key)
1524 {
1525         struct yaca_key_simple_s *simple_key = key_get_simple(key);
1526         struct yaca_key_evp_s *evp_key = key_get_evp(key);
1527
1528         if (simple_key != NULL)
1529                 yaca_free(simple_key);
1530
1531         if (evp_key != NULL) {
1532                 EVP_PKEY_free(evp_key->evp);
1533                 yaca_free(evp_key);
1534         }
1535 }
1536
1537 API int yaca_key_derive_dh(const yaca_key_h prv_key,
1538                            const yaca_key_h pub_key,
1539                            yaca_key_h *sym_key)
1540 {
1541         int ret;
1542         struct yaca_key_evp_s *lprv_key = key_get_evp(prv_key);
1543         struct yaca_key_evp_s *lpub_key = key_get_evp(pub_key);
1544         struct yaca_key_simple_s *nk = NULL;
1545         size_t nk_len;
1546         EVP_PKEY_CTX *ctx;
1547
1548         if (lprv_key == NULL || lpub_key == NULL || sym_key == NULL ||
1549             (!(lprv_key->key.type == YACA_KEY_TYPE_DH_PRIV &&
1550                lpub_key->key.type == YACA_KEY_TYPE_DH_PUB)
1551             &&
1552              !(lprv_key->key.type == YACA_KEY_TYPE_EC_PRIV &&
1553                lpub_key->key.type == YACA_KEY_TYPE_EC_PUB)))
1554                 return YACA_ERROR_INVALID_PARAMETER;
1555
1556         ctx = EVP_PKEY_CTX_new(lprv_key->evp, NULL);
1557         if (ctx == NULL) {
1558                 ret = YACA_ERROR_INTERNAL;
1559                 ERROR_DUMP(ret);
1560                 goto exit;
1561         }
1562
1563         ret = EVP_PKEY_derive_init(ctx);
1564         if (ret != 1) {
1565                 ret = YACA_ERROR_INTERNAL;
1566                 ERROR_DUMP(ret);
1567                 goto exit;
1568         }
1569
1570         ret = EVP_PKEY_derive_set_peer(ctx, lpub_key->evp);
1571         if (ret != 1) {
1572                 ret = YACA_ERROR_INTERNAL;
1573                 ERROR_DUMP(ret);
1574                 goto exit;
1575         }
1576
1577         ret = EVP_PKEY_derive(ctx, NULL, &nk_len);
1578         if (ret != 1) {
1579                 ret = YACA_ERROR_INTERNAL;
1580                 ERROR_DUMP(ret);
1581                 goto exit;
1582         }
1583
1584         if (nk_len == 0 || nk_len > SIZE_MAX / 8) {
1585                 ret = YACA_ERROR_INVALID_PARAMETER;
1586                 goto exit;
1587         }
1588
1589         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + nk_len, (void**)&nk);
1590         if (ret != YACA_ERROR_NONE)
1591                 goto exit;
1592
1593         ret = EVP_PKEY_derive(ctx, (unsigned char*)nk->d, &nk_len);
1594         if (ret != 1) {
1595                 ret = YACA_ERROR_INTERNAL;
1596                 ERROR_DUMP(ret);
1597                 goto exit;
1598         }
1599
1600         nk->bit_len = nk_len * 8;
1601         nk->key.type = YACA_KEY_TYPE_SYMMETRIC;
1602         *sym_key = (yaca_key_h)nk;
1603         nk = NULL;
1604         ret = YACA_ERROR_NONE;
1605
1606 exit:
1607         EVP_PKEY_CTX_free(ctx);
1608         yaca_free(nk);
1609         return ret;
1610 }
1611
1612 API int yaca_key_derive_pbkdf2(const char *password,
1613                                const char *salt,
1614                                size_t salt_len,
1615                                size_t iterations,
1616                                yaca_digest_algorithm_e algo,
1617                                size_t key_bit_len,
1618                                yaca_key_h *key)
1619 {
1620         const EVP_MD *md;
1621         struct yaca_key_simple_s *nk;
1622         size_t key_byte_len = key_bit_len / 8;
1623         int ret;
1624
1625         if (password == NULL ||
1626             (salt == NULL && salt_len > 0) || (salt != NULL && salt_len == 0) ||
1627             iterations == 0 || key_bit_len == 0 || key == NULL)
1628                 return YACA_ERROR_INVALID_PARAMETER;
1629
1630         if (key_bit_len % 8) /* Key length must be multiple of 8-bit_len */
1631                 return YACA_ERROR_INVALID_PARAMETER;
1632
1633         if (iterations > INT_MAX) /* OpenSSL limitation */
1634                 return YACA_ERROR_INVALID_PARAMETER;
1635
1636         ret = digest_get_algorithm(algo, &md);
1637         if (ret != YACA_ERROR_NONE)
1638                 return ret;
1639
1640         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
1641         if (ret != YACA_ERROR_NONE)
1642                 return ret;
1643
1644         nk->bit_len = key_bit_len;
1645         nk->key.type = YACA_KEY_TYPE_SYMMETRIC; // TODO: how to handle other keys?
1646
1647         ret = PKCS5_PBKDF2_HMAC(password, -1, (const unsigned char*)salt,
1648                                 salt_len, iterations, md, key_byte_len,
1649                                 (unsigned char*)nk->d);
1650         if (ret != 1) {
1651                 ret = YACA_ERROR_INTERNAL;
1652                 ERROR_DUMP(ret);
1653                 goto exit;
1654         }
1655
1656         *key = (yaca_key_h)nk;
1657         nk = NULL;
1658         ret = YACA_ERROR_NONE;
1659 exit:
1660         yaca_free(nk);
1661
1662         return ret;
1663 }