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