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