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