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