8f02b3c95edb3fd610ac677f1769e97418f65309
[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
36 #include <yaca_crypto.h>
37 #include <yaca_error.h>
38 #include <yaca_key.h>
39
40 #include "internal.h"
41
42 /* This callback only exists to block the default OpenSSL one and
43  * allow us to check for a proper error code when the key is encrypted
44  */
45 int password_dummy_cb(char *buf, int size, int rwflag, void *u)
46 {
47         const char empty[] = "";
48
49         memcpy(buf, empty, sizeof(empty));
50
51         return sizeof(empty);
52 }
53
54 int base64_decode_length(const char *data, size_t data_len, size_t *len)
55 {
56         assert(data != NULL);
57         assert(data_len != 0);
58         assert(len != NULL);
59
60         size_t padded = 0;
61         size_t tmp_len = data_len;
62
63         if (data_len % 4 != 0)
64                 return YACA_ERROR_INVALID_PARAMETER;
65
66         if (data[tmp_len - 1] == '=') {
67                 padded = 1;
68                 if (data[tmp_len - 2] == '=')
69                         padded = 2;
70         }
71
72         *len = data_len / 4 * 3 - padded;
73         return YACA_ERROR_NONE;
74 }
75
76 #define TMP_BUF_LEN 512
77
78 int base64_decode(const char *data, size_t data_len, BIO **output)
79 {
80         assert(data != NULL);
81         assert(data_len != 0);
82         assert(output != NULL);
83
84         int ret;
85         BIO *b64 = NULL;
86         BIO *src = NULL;
87         BIO *dst = NULL;
88         char tmpbuf[TMP_BUF_LEN];
89         size_t b64_len;
90         char *out;
91         long out_len;
92
93         /* This is because of BIO_new_mem_buf() having its length param typed int */
94         if (data_len > INT_MAX)
95                 return YACA_ERROR_INVALID_PARAMETER;
96
97         /* First phase of correctness checking, calculate expected output length */
98         ret = base64_decode_length(data, data_len, &b64_len);
99         if (ret != YACA_ERROR_NONE)
100                 return ret;
101
102         b64 = BIO_new(BIO_f_base64());
103         if (b64 == NULL) {
104                 ret = YACA_ERROR_INTERNAL;
105                 ERROR_DUMP(ret);
106                 return ret;
107         }
108
109         src = BIO_new_mem_buf(data, data_len);
110         if (src == NULL) {
111                 ret = YACA_ERROR_INTERNAL;
112                 ERROR_DUMP(ret);
113                 goto exit;
114         }
115
116         BIO_push(b64, src);
117
118         dst = BIO_new(BIO_s_mem());
119         if (dst == NULL) {
120                 ret = YACA_ERROR_INTERNAL;
121                 ERROR_DUMP(ret);
122                 goto exit;
123         }
124
125         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
126
127         /* Try to decode */
128         for (;;) {
129                 ret = BIO_read(b64, tmpbuf, TMP_BUF_LEN);
130                 if (ret < 0) {
131                         ret = YACA_ERROR_INTERNAL;
132                         ERROR_DUMP(ret);
133                         goto exit;
134                 }
135
136                 if (ret == YACA_ERROR_NONE)
137                         break;
138
139                 if (BIO_write(dst, tmpbuf, ret) != ret) {
140                         ret = YACA_ERROR_INTERNAL;
141                         ERROR_DUMP(ret);
142                         goto exit;
143                 }
144         }
145
146         BIO_flush(dst);
147
148         /* Check wether the length of the decoded data is what we expected */
149         out_len = BIO_get_mem_data(dst, &out);
150         if (out_len < 0) {
151                 ret = YACA_ERROR_INTERNAL;
152                 ERROR_DUMP(ret);
153                 goto exit;
154         }
155         if ((size_t)out_len != b64_len) {
156                 ret = YACA_ERROR_INVALID_PARAMETER;
157                 goto exit;
158         }
159
160         *output = dst;
161         dst = NULL;
162         ret = YACA_ERROR_NONE;
163
164 exit:
165         BIO_free_all(b64);
166         BIO_free_all(dst);
167
168         return ret;
169 }
170
171 int import_simple(yaca_key_h *key,
172                   yaca_key_type_e key_type,
173                   const char *data,
174                   size_t data_len)
175 {
176         assert(key != NULL);
177         assert(data != NULL);
178         assert(data_len != 0);
179
180         int ret;
181         BIO *decoded = NULL;
182         const char *key_data;
183         size_t key_data_len;
184         struct yaca_key_simple_s *nk = NULL;
185
186         ret = base64_decode(data, data_len, &decoded);
187         if (ret == YACA_ERROR_NONE) {
188                 /* Conversion successfull, get the BASE64 */
189                 long len = BIO_get_mem_data(decoded, &key_data);
190                 if (len <= 0 || key_data == NULL) {
191                         ret = YACA_ERROR_INTERNAL;
192                         ERROR_DUMP(ret);
193                         return ret;
194                 }
195                 key_data_len = len;
196         } else if (ret == YACA_ERROR_INVALID_PARAMETER) {
197                 /* This was not BASE64 or it was corrupted, treat as RAW */
198                 key_data_len = data_len;
199                 key_data = data;
200         } else {
201                 /* Some other, possibly unrecoverable error, give up */
202                 return ret;
203         }
204
205         /* key_bits has to fit in size_t */
206         if (key_data_len > SIZE_MAX / 8) {
207                 ret = YACA_ERROR_INVALID_PARAMETER;
208                 goto exit;
209         }
210
211         /* DES key length verification */
212         if (key_type == YACA_KEY_TYPE_DES) {
213                 size_t key_bits = key_data_len * 8;
214                 if (key_bits != YACA_KEY_LENGTH_UNSAFE_64BIT &&
215                     key_bits != YACA_KEY_LENGTH_UNSAFE_128BIT &&
216                     key_bits != YACA_KEY_LENGTH_192BIT) {
217                         ret = YACA_ERROR_INVALID_PARAMETER;
218                         goto exit;
219                 }
220         }
221
222         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_data_len, (void**)&nk);
223         if (ret != YACA_ERROR_NONE)
224                 goto exit;
225
226         memcpy(nk->d, key_data, key_data_len);
227         nk->bits = key_data_len * 8;
228         nk->key.type = key_type;
229
230         *key = (yaca_key_h)nk;
231         nk = NULL;
232         ret = YACA_ERROR_NONE;
233
234 exit:
235         BIO_free_all(decoded);
236
237         return ret;
238 }
239
240 bool check_import_wrong_pass()
241 {
242         unsigned long err = ERR_peek_error();
243         unsigned long err_bad_password_1 = ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT);
244         unsigned long err_bad_password_2 = ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT);
245
246         if (err == err_bad_password_1 || err == err_bad_password_2)
247                 return true;
248
249         return false;
250 }
251
252 int import_evp(yaca_key_h *key,
253                yaca_key_type_e key_type,
254                const char *password,
255                const char *data,
256                size_t data_len)
257 {
258         assert(key != NULL);
259         assert(password == NULL || password[0] != '\0');
260         assert(data != NULL);
261         assert(data_len != 0);
262
263         int ret;
264         BIO *src = NULL;
265         EVP_PKEY *pkey = NULL;
266         bool wrong_pass = false;
267         pem_password_cb *cb = NULL;
268         bool private;
269         yaca_key_type_e type;
270         struct yaca_key_evp_s *nk = NULL;
271
272         /* Neither PEM nor DER will ever be shorter then 4 bytes (12 seems
273          * to be minimum for DER, much more for PEM). This is just to make
274          * sure we have at least 4 bytes for strncmp() below.
275          */
276         if (data_len < 4)
277                 return YACA_ERROR_INVALID_PARAMETER;
278
279         /* This is because of BIO_new_mem_buf() having its length param typed int */
280         if (data_len > INT_MAX)
281                 return YACA_ERROR_INVALID_PARAMETER;
282
283         src = BIO_new_mem_buf(data, data_len);
284         if (src == NULL) {
285                 ERROR_DUMP(YACA_ERROR_INTERNAL);
286                 return YACA_ERROR_INTERNAL;
287         }
288
289         /* Block the default OpenSSL password callback */
290         if (password == NULL)
291                 cb = password_dummy_cb;
292
293         /* Possible PEM */
294         if (strncmp("----", data, 4) == 0) {
295                 if (pkey == NULL && !wrong_pass) {
296                         BIO_reset(src);
297                         pkey = PEM_read_bio_PrivateKey(src, NULL, cb, (void*)password);
298                         if (check_import_wrong_pass())
299                                 wrong_pass = true;
300                         private = true;
301                         ERROR_CLEAR();
302                 }
303
304                 if (pkey == NULL && !wrong_pass) {
305                         BIO_reset(src);
306                         pkey = PEM_read_bio_PUBKEY(src, NULL, cb, (void*)password);
307                         if (check_import_wrong_pass())
308                                 wrong_pass = true;
309                         private = false;
310                         ERROR_CLEAR();
311                 }
312
313                 if (pkey == NULL && !wrong_pass) {
314                         BIO_reset(src);
315                         X509 *x509 = PEM_read_bio_X509(src, NULL, cb, (void*)password);
316                         if (check_import_wrong_pass())
317                                 wrong_pass = true;
318                         if (x509 != NULL)
319                                 pkey = X509_get_pubkey(x509);
320                         X509_free(x509);
321                         private = false;
322                         ERROR_CLEAR();
323                 }
324         }
325         /* Possible DER */
326         else {
327                 if (pkey == NULL && !wrong_pass) {
328                         BIO_reset(src);
329                         pkey = d2i_PKCS8PrivateKey_bio(src, NULL, cb, (void*)password);
330                         if (check_import_wrong_pass())
331                                 wrong_pass = true;
332                         private = true;
333                         ERROR_CLEAR();
334                 }
335
336                 if (pkey == NULL && !wrong_pass) {
337                         BIO_reset(src);
338                         pkey = d2i_PrivateKey_bio(src, NULL);
339                         private = true;
340                         ERROR_CLEAR();
341                 }
342
343                 if (pkey == NULL && !wrong_pass) {
344                         BIO_reset(src);
345                         pkey = d2i_PUBKEY_bio(src, NULL);
346                         private = false;
347                         ERROR_CLEAR();
348                 }
349         }
350
351         BIO_free(src);
352
353         if (wrong_pass)
354                 return YACA_ERROR_INVALID_PASSWORD;
355
356         if (pkey == NULL)
357                 return YACA_ERROR_INVALID_PARAMETER;
358
359         switch (EVP_PKEY_type(pkey->type)) {
360         case EVP_PKEY_RSA:
361                 type = private ? YACA_KEY_TYPE_RSA_PRIV : YACA_KEY_TYPE_RSA_PUB;
362                 break;
363
364         case EVP_PKEY_DSA:
365                 type = private ? YACA_KEY_TYPE_DSA_PRIV : YACA_KEY_TYPE_DSA_PUB;
366                 break;
367
368 //      case EVP_PKEY_EC:
369 //              type = private ? YACA_KEY_TYPE_EC_PRIV : YACA_KEY_TYPE_EC_PUB;
370 //              break;
371
372         default:
373                 ret = YACA_ERROR_INVALID_PARAMETER;
374                 goto exit;
375         }
376
377         if (type != key_type) {
378                 ret = YACA_ERROR_INVALID_PARAMETER;
379                 goto exit;
380         }
381
382         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
383         if (ret != YACA_ERROR_NONE)
384                 goto exit;
385
386         nk->evp = pkey;
387         *key = (yaca_key_h)nk;
388         (*key)->type = type;
389
390         pkey = NULL;
391         ret = YACA_ERROR_NONE;
392
393 exit:
394         EVP_PKEY_free(pkey);
395
396         return ret;
397 }
398
399 int export_simple_raw(struct yaca_key_simple_s *simple_key,
400                       char **data,
401                       size_t *data_len)
402 {
403         int ret;
404         assert(simple_key != NULL);
405         assert(data != NULL);
406         assert(data_len != NULL);
407
408         size_t key_len = simple_key->bits / 8;
409
410         assert(key_len > 0);
411
412         ret = yaca_malloc(key_len, (void**)data);
413         if (ret != YACA_ERROR_NONE)
414                 return ret;
415
416         memcpy(*data, simple_key->d, key_len);
417         *data_len = key_len;
418
419         return YACA_ERROR_NONE;
420 }
421
422 int export_simple_base64(struct yaca_key_simple_s *simple_key,
423                          char **data,
424                          size_t *data_len)
425 {
426         assert(simple_key != NULL);
427         assert(data != NULL);
428         assert(data_len != NULL);
429
430         int ret;
431         size_t key_len = simple_key->bits / 8;
432         BIO *b64;
433         BIO *mem;
434         char *bio_data;
435         long bio_data_len;
436
437         b64 = BIO_new(BIO_f_base64());
438         if (b64 == NULL) {
439                 ret = YACA_ERROR_INTERNAL;
440                 ERROR_DUMP(ret);
441                 return ret;
442         }
443
444         mem = BIO_new(BIO_s_mem());
445         if (mem == NULL) {
446                 ret = YACA_ERROR_INTERNAL;
447                 ERROR_DUMP(ret);
448                 goto exit;
449         }
450
451         BIO_push(b64, mem);
452         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
453
454         ret = BIO_write(b64, simple_key->d, key_len);
455         if (ret <= 0 || (unsigned)ret != key_len) {
456                 ret = YACA_ERROR_INTERNAL;
457                 ERROR_DUMP(ret);
458                 goto exit;
459         }
460
461         ret = BIO_flush(b64);
462         if (ret <= 0) {
463                 ret = YACA_ERROR_INTERNAL;
464                 ERROR_DUMP(ret);
465                 goto exit;
466         }
467
468         bio_data_len = BIO_get_mem_data(mem, &bio_data);
469         if (bio_data_len <= 0) {
470                 ret = YACA_ERROR_INTERNAL;
471                 ERROR_DUMP(ret);
472                 goto exit;
473         }
474
475         ret = yaca_malloc(bio_data_len, (void**)data);
476         if (ret != YACA_ERROR_NONE)
477                 goto exit;
478
479         memcpy(*data, bio_data, bio_data_len);
480         *data_len = bio_data_len;
481         ret = YACA_ERROR_NONE;
482
483 exit:
484         BIO_free_all(b64);
485
486         return ret;
487 }
488
489 int export_evp_default_bio(struct yaca_key_evp_s *evp_key,
490                            yaca_key_file_format_e key_file_fmt,
491                            const char *password,
492                            BIO *mem)
493 {
494         assert(evp_key != NULL);
495         assert(password == NULL || password[0] != '\0');
496         assert(mem != NULL);
497
498         int ret;
499         const EVP_CIPHER *enc = NULL;
500
501         if (password != NULL)
502                 enc = EVP_aes_256_cbc();
503
504         switch (key_file_fmt) {
505
506         case YACA_KEY_FILE_FORMAT_PEM:
507                 switch (evp_key->key.type) {
508
509                 case YACA_KEY_TYPE_RSA_PRIV:
510                         ret = PEM_write_bio_RSAPrivateKey(mem, EVP_PKEY_get0(evp_key->evp),
511                                                           enc, NULL, 0, NULL, (void*)password);
512                         break;
513                 case YACA_KEY_TYPE_DSA_PRIV:
514                         ret = PEM_write_bio_DSAPrivateKey(mem, EVP_PKEY_get0(evp_key->evp),
515                                                           enc, NULL, 0, NULL, (void*)password);
516                         break;
517
518                 case YACA_KEY_TYPE_RSA_PUB:
519                 case YACA_KEY_TYPE_DSA_PUB:
520                         ret = PEM_write_bio_PUBKEY(mem, evp_key->evp);
521                         break;
522
523 //              case YACA_KEY_TYPE_DH_PRIV:
524 //              case YACA_KEY_TYPE_DH_PUB:
525 //              case YACA_KEY_TYPE_EC_PRIV:
526 //              case YACA_KEY_TYPE_EC_PUB:
527 //                      TODO NOT_IMPLEMENTED
528                 default:
529                         return YACA_ERROR_INVALID_PARAMETER;
530                 }
531
532                 break;
533
534         case YACA_KEY_FILE_FORMAT_DER:
535                 switch (evp_key->key.type) {
536
537                 case YACA_KEY_TYPE_RSA_PRIV:
538                         ret = i2d_RSAPrivateKey_bio(mem, EVP_PKEY_get0(evp_key->evp));
539                         break;
540
541                 case YACA_KEY_TYPE_DSA_PRIV:
542                         ret = i2d_DSAPrivateKey_bio(mem, EVP_PKEY_get0(evp_key->evp));
543                         break;
544
545                 case YACA_KEY_TYPE_RSA_PUB:
546                 case YACA_KEY_TYPE_DSA_PUB:
547                         ret = i2d_PUBKEY_bio(mem, evp_key->evp);
548                         break;
549
550 //              case YACA_KEY_TYPE_DH_PRIV:
551 //              case YACA_KEY_TYPE_DH_PUB:
552 //              case YACA_KEY_TYPE_EC_PRIV:
553 //              case YACA_KEY_TYPE_EC_PUB:
554 //                      TODO NOT_IMPLEMENTED
555                 default:
556                         return YACA_ERROR_INVALID_PARAMETER;
557                 }
558
559                 break;
560
561         default:
562                 return YACA_ERROR_INVALID_PARAMETER;
563         }
564
565         if (ret <= 0) {
566                 ret = YACA_ERROR_INTERNAL;
567                 ERROR_DUMP(ret);
568                 return ret;
569         }
570
571         return YACA_ERROR_NONE;
572 }
573
574 int export_evp_pkcs8_bio(struct yaca_key_evp_s *evp_key,
575                          yaca_key_file_format_e key_file_fmt,
576                          const char *password,
577                          BIO *mem)
578 {
579         assert(evp_key != NULL);
580         assert(password == NULL || password[0] != '\0');
581         assert(mem != NULL);
582
583         int ret;
584         int nid = -1;
585
586         if (password != NULL)
587                 nid = NID_pbeWithMD5AndDES_CBC;
588
589         switch (key_file_fmt) {
590
591         case YACA_KEY_FILE_FORMAT_PEM:
592                 switch (evp_key->key.type) {
593
594                 case YACA_KEY_TYPE_RSA_PRIV:
595                 case YACA_KEY_TYPE_DSA_PRIV:
596                         ret = PEM_write_bio_PKCS8PrivateKey_nid(mem, evp_key->evp, nid,
597                                                                 NULL, 0, NULL, (void*)password);
598                         break;
599 //              case YACA_KEY_TYPE_DH_PRIV:
600 //              case YACA_KEY_TYPE_EC_PRIV:
601 //                      TODO NOT_IMPLEMENTED
602                 default:
603                         /* Public keys are not supported by PKCS8 */
604                         return YACA_ERROR_INVALID_PARAMETER;
605                 }
606
607                 break;
608
609         case YACA_KEY_FILE_FORMAT_DER:
610                 switch (evp_key->key.type) {
611
612                 case YACA_KEY_TYPE_RSA_PRIV:
613                 case YACA_KEY_TYPE_DSA_PRIV:
614                         ret = i2d_PKCS8PrivateKey_nid_bio(mem, evp_key->evp, nid,
615                                                           NULL, 0, NULL, (void*)password);
616                         break;
617
618 //              case YACA_KEY_TYPE_DH_PRIV:
619 //              case YACA_KEY_TYPE_EC_PRIV:
620 //                      TODO NOT_IMPLEMENTED
621                 default:
622                         /* Public keys are not supported by PKCS8 */
623                         return YACA_ERROR_INVALID_PARAMETER;
624                 }
625
626                 break;
627
628         default:
629                 return YACA_ERROR_INVALID_PARAMETER;
630         }
631
632         if (ret <= 0) {
633                 ret = YACA_ERROR_INTERNAL;
634                 ERROR_DUMP(ret);
635                 return ret;
636         }
637
638         return YACA_ERROR_NONE;
639 }
640
641 int export_evp(struct yaca_key_evp_s *evp_key,
642                yaca_key_format_e key_fmt,
643                yaca_key_file_format_e key_file_fmt,
644                const char *password,
645                char **data,
646                size_t *data_len)
647 {
648         assert(evp_key != NULL);
649         assert(password == NULL || password[0] != '\0');
650         assert(data != NULL);
651         assert(data_len != NULL);
652
653         int ret = YACA_ERROR_NONE;
654         BIO *mem;
655         char *bio_data;
656         long bio_data_len;
657
658         mem = BIO_new(BIO_s_mem());
659         if (mem == NULL) {
660                 ret = YACA_ERROR_INTERNAL;
661                 ERROR_DUMP(ret);
662                 return ret;
663         }
664
665         switch (key_fmt) {
666         case YACA_KEY_FORMAT_DEFAULT:
667                 ret = export_evp_default_bio(evp_key, key_file_fmt, password, mem);
668                 break;
669         case YACA_KEY_FORMAT_PKCS8:
670                 ret = export_evp_pkcs8_bio(evp_key, key_file_fmt, password, mem);
671                 break;
672         default:
673                 ret = YACA_ERROR_INVALID_PARAMETER;
674                 break;
675         }
676
677         if (ret != YACA_ERROR_NONE)
678                 goto exit;
679
680         ret = BIO_flush(mem);
681         if (ret <= 0) {
682                 ret = YACA_ERROR_INTERNAL;
683                 ERROR_DUMP(ret);
684                 goto exit;
685         }
686
687         bio_data_len = BIO_get_mem_data(mem, &bio_data);
688         if (bio_data_len <= 0) {
689                 ret = YACA_ERROR_INTERNAL;
690                 ERROR_DUMP(ret);
691                 goto exit;
692         }
693
694         ret = yaca_malloc(bio_data_len, (void**)data);
695         if (ret != YACA_ERROR_NONE)
696                 goto exit;
697
698         memcpy(*data, bio_data, bio_data_len);
699         *data_len = bio_data_len;
700         ret = YACA_ERROR_NONE;
701
702 exit:
703         BIO_free_all(mem);
704
705         return ret;
706 }
707
708 int gen_simple(struct yaca_key_simple_s **out, size_t key_bits)
709 {
710         assert(out != NULL);
711
712         int ret;
713         struct yaca_key_simple_s *nk;
714         size_t key_byte_len = key_bits / 8;
715
716         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
717         if (ret != YACA_ERROR_NONE)
718                 return ret;
719
720         nk->bits = key_bits;
721
722         ret = yaca_randomize_bytes(nk->d, key_byte_len);
723         if (ret != YACA_ERROR_NONE)
724                 return ret;
725
726         *out = nk;
727         return YACA_ERROR_NONE;
728 }
729
730 int gen_simple_des(struct yaca_key_simple_s **out, size_t key_bits)
731 {
732         assert(out != NULL);
733
734         if (key_bits != YACA_KEY_LENGTH_UNSAFE_64BIT &&
735             key_bits != YACA_KEY_LENGTH_UNSAFE_128BIT &&
736             key_bits != YACA_KEY_LENGTH_192BIT)
737                 return YACA_ERROR_INVALID_PARAMETER;
738
739         int ret;
740         struct yaca_key_simple_s *nk;
741         size_t key_byte_len = key_bits / 8;
742
743         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
744         if (ret != YACA_ERROR_NONE)
745                 return ret;
746
747         DES_cblock *des_key = (DES_cblock*)nk->d;
748         if (key_byte_len >= 8) {
749                 ret = DES_random_key(des_key);
750                 if (ret != 1) {
751                         ret = YACA_ERROR_INTERNAL;
752                         ERROR_DUMP(ret);
753                         goto exit;
754                 }
755         }
756         if (key_byte_len >= 16) {
757                 ret = DES_random_key(des_key + 1);
758                 if (ret != 1) {
759                         ret = YACA_ERROR_INTERNAL;
760                         ERROR_DUMP(ret);
761                         goto exit;
762                 }
763         }
764         if (key_byte_len >= 24) {
765                 ret = DES_random_key(des_key + 2);
766                 if (ret != 1) {
767                         ret = YACA_ERROR_INTERNAL;
768                         ERROR_DUMP(ret);
769                         goto exit;
770                 }
771         }
772
773         nk->bits = key_bits;
774         *out = nk;
775         nk = NULL;
776         ret = YACA_ERROR_NONE;
777
778 exit:
779         yaca_free(nk);
780
781         return ret;
782 }
783
784 // TODO: consider merging gen_evp_*, they share awful lot of common code
785 int gen_evp_rsa(struct yaca_key_evp_s **out, size_t key_bits)
786 {
787         assert(out != NULL);
788         assert(key_bits > 0);
789         assert(key_bits % 8 == 0);
790
791         int ret;
792         struct yaca_key_evp_s *nk;
793         EVP_PKEY_CTX *ctx;
794         EVP_PKEY *pkey = NULL;
795
796         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
797         if (ret != YACA_ERROR_NONE)
798                 return ret;
799
800         ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
801         if (ctx == NULL) {
802                 ret = YACA_ERROR_INTERNAL;
803                 ERROR_DUMP(ret);
804                 goto exit;
805         }
806
807         ret = EVP_PKEY_keygen_init(ctx);
808         if (ret != 1) {
809                 ret = YACA_ERROR_INTERNAL;
810                 ERROR_DUMP(ret);
811                 goto exit;
812         }
813
814         ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits);
815         if (ret != 1) {
816                 ret = ERROR_HANDLE();
817                 goto exit;
818         }
819
820         ret = EVP_PKEY_keygen(ctx, &pkey);
821         if (ret != 1) {
822                 ret = YACA_ERROR_INTERNAL;
823                 ERROR_DUMP(ret);
824                 goto exit;
825         }
826
827         nk->evp = pkey;
828         pkey = NULL;
829         *out = nk;
830         nk = NULL;
831
832         ret = YACA_ERROR_NONE;
833
834 exit:
835         EVP_PKEY_CTX_free(ctx);
836         yaca_free(nk);
837
838         return ret;
839 }
840
841 int gen_evp_dsa(struct yaca_key_evp_s **out, size_t key_bits)
842 {
843         assert(out != NULL);
844         assert(key_bits > 0);
845         assert(key_bits % 8 == 0);
846
847         /* Openssl generates 512-bit key for key lengths smaller than 512. It also
848          * rounds key size to multiplication of 64. */
849         if (key_bits < 512 || key_bits % 64 != 0)
850                 return YACA_ERROR_INVALID_PARAMETER;
851
852         int ret;
853         struct yaca_key_evp_s *nk;
854         EVP_PKEY_CTX *pctx = NULL;
855         EVP_PKEY_CTX *kctx = NULL;
856         EVP_PKEY *pkey = NULL;
857         EVP_PKEY *params = NULL;
858
859         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
860         if (ret != YACA_ERROR_NONE)
861                 return ret;
862
863         pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
864         if (pctx == NULL) {
865                 ret = YACA_ERROR_INTERNAL;
866                 ERROR_DUMP(ret);
867                 goto exit;
868         }
869
870         ret = EVP_PKEY_paramgen_init(pctx);
871         if (ret != 1) {
872                 ret = YACA_ERROR_INTERNAL;
873                 ERROR_DUMP(ret);
874                 goto exit;
875         }
876
877         ret = EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, key_bits);
878         if (ret != 1) {
879                 ret = ERROR_HANDLE();
880                 goto exit;
881         }
882
883         ret = EVP_PKEY_paramgen(pctx, &params);
884         if (ret != 1) {
885                 ret = YACA_ERROR_INTERNAL;
886                 ERROR_DUMP(ret);
887                 goto exit;
888         }
889
890         kctx = EVP_PKEY_CTX_new(params, NULL);
891         if (kctx == NULL) {
892                 ret = YACA_ERROR_INTERNAL;
893                 ERROR_DUMP(ret);
894                 goto exit;
895         }
896
897         ret = EVP_PKEY_keygen_init(kctx);
898         if (ret != 1) {
899                 ret = YACA_ERROR_INTERNAL;
900                 ERROR_DUMP(ret);
901                 goto exit;
902         }
903
904         ret = EVP_PKEY_keygen(kctx, &pkey);
905         if (ret != 1) {
906                 ret = YACA_ERROR_INTERNAL;
907                 ERROR_DUMP(ret);
908                 goto exit;
909         }
910
911         nk->evp = pkey;
912         pkey = NULL;
913         *out = nk;
914         nk = NULL;
915
916         ret = YACA_ERROR_NONE;
917
918 exit:
919         EVP_PKEY_CTX_free(kctx);
920         EVP_PKEY_free(params);
921         EVP_PKEY_CTX_free(pctx);
922         yaca_free(nk);
923
924         return ret;
925 }
926
927 struct yaca_key_simple_s *key_get_simple(const yaca_key_h key)
928 {
929         struct yaca_key_simple_s *k;
930
931         if (key == YACA_KEY_NULL)
932                 return NULL;
933
934         switch (key->type) {
935         case YACA_KEY_TYPE_SYMMETRIC:
936         case YACA_KEY_TYPE_DES:
937         case YACA_KEY_TYPE_IV:
938                 k = (struct yaca_key_simple_s *)key;
939
940                 /* sanity check */
941                 assert(k->bits != 0);
942                 assert(k->bits % 8 == 0);
943                 assert(k->d != NULL);
944
945                 return k;
946         default:
947                 return NULL;
948         }
949 }
950
951 struct yaca_key_evp_s *key_get_evp(const yaca_key_h key)
952 {
953         struct yaca_key_evp_s *k;
954
955         if (key == YACA_KEY_NULL)
956                 return NULL;
957
958         switch (key->type) {
959         case YACA_KEY_TYPE_RSA_PUB:
960         case YACA_KEY_TYPE_RSA_PRIV:
961         case YACA_KEY_TYPE_DSA_PUB:
962         case YACA_KEY_TYPE_DSA_PRIV:
963                 k = (struct yaca_key_evp_s *)key;
964
965                 /* sanity check */
966                 assert(k->evp != NULL);
967
968                 return k;
969         default:
970                 return NULL;
971         }
972 }
973
974 API int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type)
975 {
976         const struct yaca_key_s *lkey = (const struct yaca_key_s *)key;
977
978         if (lkey == NULL || key_type == NULL)
979                 return YACA_ERROR_INVALID_PARAMETER;
980
981         *key_type = lkey->type;
982         return YACA_ERROR_NONE;
983 }
984
985 API int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len)
986 {
987         const struct yaca_key_simple_s *simple_key = key_get_simple(key);
988         const struct yaca_key_evp_s *evp_key = key_get_evp(key);
989
990         if (key_bit_len == NULL)
991                 return YACA_ERROR_INVALID_PARAMETER;
992
993         if (simple_key != NULL) {
994                 *key_bit_len = simple_key->bits;
995                 return YACA_ERROR_NONE;
996         }
997
998         if (evp_key != NULL) {
999                 int ret;
1000
1001                 // TODO: handle ECC keys when they're implemented
1002                 ret = EVP_PKEY_bits(evp_key->evp);
1003                 if (ret <= 0) {
1004                         ret = YACA_ERROR_INTERNAL;
1005                         ERROR_DUMP(ret);
1006                         return ret;
1007                 }
1008
1009                 *key_bit_len = ret;
1010                 return YACA_ERROR_NONE;
1011         }
1012
1013         return YACA_ERROR_INVALID_PARAMETER;
1014 }
1015
1016 API int yaca_key_import(yaca_key_type_e key_type,
1017                         const char *password,
1018                         const char *data,
1019                         size_t data_len,
1020                         yaca_key_h *key)
1021 {
1022         if (key == NULL || data == NULL || data_len == 0)
1023                 return YACA_ERROR_INVALID_PARAMETER;
1024
1025         /* allow an empty password, OpenSSL returns an error with "" */
1026         if (password != NULL && password[0] == '\0')
1027                 password = NULL;
1028
1029         switch (key_type) {
1030         case YACA_KEY_TYPE_SYMMETRIC:
1031         case YACA_KEY_TYPE_DES:
1032         case YACA_KEY_TYPE_IV:
1033                 if (password != NULL)
1034                         return YACA_ERROR_INVALID_PARAMETER;
1035                 return import_simple(key, key_type, data, data_len);
1036         case YACA_KEY_TYPE_RSA_PUB:
1037         case YACA_KEY_TYPE_RSA_PRIV:
1038         case YACA_KEY_TYPE_DSA_PUB:
1039         case YACA_KEY_TYPE_DSA_PRIV:
1040                 return import_evp(key, key_type, password, data, data_len);
1041 //      case YACA_KEY_TYPE_DH_PUB:
1042 //      case YACA_KEY_TYPE_DH_PRIV:
1043 //      case YACA_KEY_TYPE_EC_PUB:
1044 //      case YACA_KEY_TYPE_EC_PRIV:
1045 //              TODO NOT_IMPLEMENTED
1046         default:
1047                 return YACA_ERROR_INVALID_PARAMETER;
1048         }
1049 }
1050
1051 API int yaca_key_export(const yaca_key_h key,
1052                         yaca_key_format_e key_fmt,
1053                         yaca_key_file_format_e key_file_fmt,
1054                         const char *password,
1055                         char **data,
1056                         size_t *data_len)
1057 {
1058         struct yaca_key_simple_s *simple_key = key_get_simple(key);
1059         struct yaca_key_evp_s *evp_key = key_get_evp(key);
1060
1061         if (data == NULL || data_len == NULL)
1062                 return YACA_ERROR_INVALID_PARAMETER;
1063
1064         /* allow an empty password, OpenSSL returns an error with "" */
1065         if (password != NULL && password[0] == '\0')
1066                 password = NULL;
1067
1068         if (password != NULL && simple_key != NULL)
1069                 return YACA_ERROR_INVALID_PARAMETER;
1070
1071         if (key_fmt == YACA_KEY_FORMAT_DEFAULT &&
1072             key_file_fmt == YACA_KEY_FILE_FORMAT_RAW &&
1073             simple_key != NULL)
1074                 return export_simple_raw(simple_key, data, data_len);
1075
1076         if (key_fmt == YACA_KEY_FORMAT_DEFAULT &&
1077             key_file_fmt == YACA_KEY_FILE_FORMAT_BASE64 &&
1078             simple_key != NULL)
1079                 return export_simple_base64(simple_key, data, data_len);
1080
1081         if (evp_key != NULL)
1082                 return export_evp(evp_key, key_fmt, key_file_fmt,
1083                                   password, data, data_len);
1084
1085         return YACA_ERROR_INVALID_PARAMETER;
1086 }
1087
1088 API int yaca_key_generate(yaca_key_type_e key_type,
1089                           size_t key_bit_len,
1090                           yaca_key_h *key)
1091 {
1092         int ret;
1093         struct yaca_key_simple_s *nk_simple = NULL;
1094         struct yaca_key_evp_s *nk_evp = NULL;
1095
1096         if (key == NULL || key_bit_len == 0 || key_bit_len % 8 != 0)
1097                 return YACA_ERROR_INVALID_PARAMETER;
1098
1099         switch (key_type) {
1100         case YACA_KEY_TYPE_SYMMETRIC:
1101         case YACA_KEY_TYPE_IV:
1102                 ret = gen_simple(&nk_simple, key_bit_len);
1103                 break;
1104         case YACA_KEY_TYPE_DES:
1105                 ret = gen_simple_des(&nk_simple, key_bit_len);
1106                 break;
1107         case YACA_KEY_TYPE_RSA_PRIV:
1108                 ret = gen_evp_rsa(&nk_evp, key_bit_len);
1109                 break;
1110         case YACA_KEY_TYPE_DSA_PRIV:
1111                 ret = gen_evp_dsa(&nk_evp, key_bit_len);
1112                 break;
1113 //      case YACA_KEY_TYPE_DH_PRIV:
1114 //      case YACA_KEY_TYPE_EC_PRIV:
1115 //              TODO NOT_IMPLEMENTED
1116         default:
1117                 return YACA_ERROR_INVALID_PARAMETER;
1118         }
1119
1120         if (ret != YACA_ERROR_NONE)
1121                 return ret;
1122
1123         if (nk_simple != NULL) {
1124                 nk_simple->key.type = key_type;
1125                 *key = (yaca_key_h)nk_simple;
1126         } else if (nk_evp != NULL) {
1127                 nk_evp->key.type = key_type;
1128                 *key = (yaca_key_h)nk_evp;
1129         }
1130
1131         return YACA_ERROR_NONE;
1132
1133 }
1134
1135 API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key)
1136 {
1137         int ret;
1138         struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
1139         struct yaca_key_evp_s *nk;
1140         BIO *mem = NULL;
1141         EVP_PKEY *pkey = NULL;
1142
1143         if (prv_key == YACA_KEY_NULL || evp_key == NULL || pub_key == NULL)
1144                 return YACA_ERROR_INVALID_PARAMETER;
1145
1146         ret = yaca_zalloc(sizeof(struct yaca_key_evp_s), (void**)&nk);
1147         if (ret != YACA_ERROR_NONE)
1148                 return ret;
1149
1150         mem = BIO_new(BIO_s_mem());
1151         if (mem == NULL) {
1152                 ret = YACA_ERROR_INTERNAL;
1153                 ERROR_DUMP(ret);
1154                 goto exit;
1155         }
1156
1157         ret = i2d_PUBKEY_bio(mem, evp_key->evp);
1158         if (ret != 1) {
1159                 ret = YACA_ERROR_INTERNAL;
1160                 ERROR_DUMP(ret);
1161                 goto exit;
1162         }
1163
1164         pkey = d2i_PUBKEY_bio(mem, NULL);
1165         if (pkey == NULL) {
1166                 ret = YACA_ERROR_INTERNAL;
1167                 ERROR_DUMP(ret);
1168                 goto exit;
1169         }
1170
1171         BIO_free(mem);
1172         mem = NULL;
1173
1174         switch (prv_key->type) {
1175         case YACA_KEY_TYPE_RSA_PRIV:
1176                 nk->key.type = YACA_KEY_TYPE_RSA_PUB;
1177                 break;
1178         case YACA_KEY_TYPE_DSA_PRIV:
1179                 nk->key.type = YACA_KEY_TYPE_DSA_PUB;
1180                 break;
1181 //      case YACA_KEY_TYPE_EC_PRIV:
1182 //              nk->key.type = YACA_KEY_TYPE_EC_PUB;
1183 //              break;
1184         default:
1185                 ret = YACA_ERROR_INVALID_PARAMETER;
1186                 goto exit;
1187         }
1188
1189         nk->evp = pkey;
1190         pkey = NULL;
1191         *pub_key = (yaca_key_h)nk;
1192         nk = NULL;
1193         ret = YACA_ERROR_NONE;
1194
1195 exit:
1196         EVP_PKEY_free(pkey);
1197         BIO_free(mem);
1198         yaca_free(nk);
1199
1200         return ret;
1201 }
1202
1203 API int yaca_key_destroy(yaca_key_h key)
1204 {
1205         struct yaca_key_simple_s *simple_key = key_get_simple(key);
1206         struct yaca_key_evp_s *evp_key = key_get_evp(key);
1207
1208         if (simple_key != NULL)
1209                 yaca_free(simple_key);
1210
1211         if (evp_key != NULL) {
1212                 EVP_PKEY_free(evp_key->evp);
1213                 yaca_free(evp_key);
1214         }
1215
1216         return YACA_ERROR_NONE;
1217 }
1218
1219 API int yaca_key_derive_pbkdf2(const char *password,
1220                                const char *salt,
1221                                size_t salt_len,
1222                                int iterations,
1223                                yaca_digest_algorithm_e algo,
1224                                size_t key_bit_len,
1225                                yaca_key_h *key)
1226 {
1227         const EVP_MD *md;
1228         struct yaca_key_simple_s *nk;
1229         size_t key_byte_len = key_bit_len / 8;
1230         int ret;
1231
1232         if (password == NULL || salt == NULL || salt_len == 0 ||
1233             iterations == 0 || key_bit_len == 0 || key == NULL)
1234                 return YACA_ERROR_INVALID_PARAMETER;
1235
1236         if (key_bit_len % 8) /* Key length must be multiple of 8-bits */
1237                 return YACA_ERROR_INVALID_PARAMETER;
1238
1239         ret = digest_get_algorithm(algo, &md);
1240         if (ret != YACA_ERROR_NONE)
1241                 return ret;
1242
1243         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len, (void**)&nk);
1244         if (ret != YACA_ERROR_NONE)
1245                 return ret;
1246
1247         nk->bits = key_bit_len;
1248         nk->key.type = YACA_KEY_TYPE_SYMMETRIC; // TODO: how to handle other keys?
1249
1250         ret = PKCS5_PBKDF2_HMAC(password, -1, (const unsigned char*)salt,
1251                                 salt_len, iterations, md, key_byte_len,
1252                                 (unsigned char*)nk->d);
1253         if (ret != 1) {
1254                 ret = YACA_ERROR_INTERNAL;
1255                 ERROR_DUMP(ret);
1256                 goto exit;
1257         }
1258
1259         *key = (yaca_key_h)nk;
1260         nk = NULL;
1261         ret = YACA_ERROR_NONE;
1262 exit:
1263         yaca_free(nk);
1264
1265         return ret;
1266 }