1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup dnskey DNSSEC keys functions
36  *  @ingroup dnsdbdnssec
37  *  @brief
38  *
39  *  NOT DONE
40  *
41  * @{
42  */
43 /*------------------------------------------------------------------------------
44  *
45  * USE INCLUDES */
46 #include "dnscore/dnscore-config.h"
47 
48 #if HAS_EDDSA_SUPPORT
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <arpa/inet.h>
53 #include <ctype.h>
54 
55 #include <openssl/bn.h>
56 #include <openssl/err.h>
57 #include <openssl/ssl.h>
58 #include <openssl/evp.h>
59 #include <openssl/engine.h>
60 #include "dnscore/openssl.h"
61 
62 #include "dnscore/dnscore-config.h"
63 
64 #include "dnscore/dnscore.h"
65 #include "dnscore/sys_types.h"
66 // EVP_PKEY_new_raw_public_key
67 #include "dnscore/logger.h"
68 #include "dnscore/dnskey.h"
69 #if HAS_EDDSA_SUPPORT
70 #include "dnscore/dnskey_eddsa.h"
71 #endif
72 #include "dnscore/dnssec_errors.h"
73 
74 #include "dnscore/zalloc.h"
75 
76 #define MODULE_MSG_HANDLE g_system_logger
77 
78 #define KEYECDSA_TAG 0x415344434559454b
79 #define EDDSABFR_TAG 0x5246424153444445
80 
81 #ifndef SSL_API
82 #error "SSL_API not defined"
83 #endif
84 
85 #define DNSKEY_ALGORITHM_ED25519_NID NID_ED25519
86 #define DNSKEY_ALGORITHM_ED448_NID NID_ED448
87 
88 /*
89  * Intermediary key
90  */
91 
92 struct dnskey_eddsa
93 {
94     dnskey_raw_field_t private_key;
95 };
96 
97 struct dnskey_eddsa_const
98 {
99     const dnskey_raw_field_t private_key;
100 };
101 
dnskey_eddsa_init(struct dnskey_eddsa * yeddsa)102 static void dnskey_eddsa_init(struct dnskey_eddsa *yeddsa)
103 {
104     memset(yeddsa, 0, sizeof(struct dnskey_eddsa));
105 }
106 
dnskey_eddsa_from_eddsa(struct dnskey_eddsa * yeddsa,const EVP_PKEY * eddsa)107 static void dnskey_eddsa_from_eddsa(struct dnskey_eddsa *yeddsa, const EVP_PKEY *eddsa)
108 {
109     u8 *buffer;
110     size_t size;
111     if(EVP_PKEY_get_raw_private_key(eddsa, NULL, &size) == 1)
112     {
113         ZALLOC_OBJECT_ARRAY_OR_DIE(buffer, u8, size, EDDSABFR_TAG);
114         EVP_PKEY_get_raw_private_key(eddsa, buffer, &size);
115         yeddsa->private_key.buffer = buffer;
116         yeddsa->private_key.size = size;
117     }
118 }
119 
dnskey_eddsa_finalize(struct dnskey_eddsa * yeddsa)120 static void dnskey_eddsa_finalize(struct dnskey_eddsa *yeddsa)
121 {
122     if(yeddsa->private_key.buffer != NULL)
123     {
124         ZEROMEMORY(yeddsa->private_key.buffer, yeddsa->private_key.size);
125         ZFREE_ARRAY(yeddsa->private_key.buffer, yeddsa->private_key.size);
126     }
127     dnskey_eddsa_init(yeddsa);
128 }
129 
130 static const struct dnskey_field_access ECDSA_field_access[] =
131 {
132     {"PrivateKey", offsetof(struct dnskey_eddsa,private_key), STRUCTDESCRIPTOR_RAW},
133     {"", 0, STRUCTDESCRIPTOR_NONE}
134 };
135 
136 static int
dnskey_eddsa_getnid(u8 algorithm)137 dnskey_eddsa_getnid(u8 algorithm)
138 {
139     switch(algorithm)
140     {
141         case DNSKEY_ALGORITHM_ED25519:
142         {
143             return DNSKEY_ALGORITHM_ED25519_NID;
144         }
145         case DNSKEY_ALGORITHM_ED448:
146         {
147             return DNSKEY_ALGORITHM_ED448_NID;
148         }
149         default:
150         {
151             return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
152         }
153     }
154 }
155 #if 0
156 static int
157 dnskey_eddsa_getnid_by_size(u32 size)
158 {
159     switch(size)
160     {
161         case 256:
162         {
163             return DNSKEY_ALGORITHM_ED25519_NID;
164         }
165         case 456:
166         {
167             return DNSKEY_ALGORITHM_ED448_NID;
168         }
169         default:
170         {
171             return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
172         }
173     }
174 }
175 #endif
176 static int
dnskey_eddsa_nid_to_signature_bn_size(int nid)177 dnskey_eddsa_nid_to_signature_bn_size(int nid)
178 {
179     switch(nid)
180     {
181         case DNSKEY_ALGORITHM_ED25519_NID:
182         {
183             return 32 * 2;
184         }
185         case DNSKEY_ALGORITHM_ED448_NID:
186         {
187             return 57 * 2;
188         }
189         default:
190         {
191             return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
192         }
193     }
194 }
195 
196 
197 static ya_result
dnskey_eddsa_signdigest(const dnssec_key * key,const u8 * digest,u32 digest_len,u8 * output)198 dnskey_eddsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output)
199 {
200     ya_result ret;
201     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
202     if(ctx != NULL)
203     {
204         if(EVP_DigestSignInit(ctx, NULL, NULL, NULL, key->key.ed) == 1)
205         {
206             size_t output_size = DIGEST_BUFFER_SIZE;
207             if(EVP_DigestSign(ctx, output, &output_size, digest, digest_len) == 1)
208             {
209                 ret = (ya_result)output_size;
210             }
211             else
212             {
213                 ret = ya_ssl_error();
214             }
215         }
216         else
217         {
218             ret = ya_ssl_error();
219         }
220         EVP_MD_CTX_free(ctx);
221     }
222     else
223     {
224         ret = ya_ssl_error();
225     }
226 
227     return ret;
228 }
229 
230 static bool
dnskey_eddsa_verifydigest(const dnssec_key * key,const u8 * digest,u32 digest_len,const u8 * signature,u32 signature_len)231 dnskey_eddsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len)
232 {
233     yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES);
234 
235 #if DEBUG
236     log_debug6("eddsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature);
237     log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32);
238     log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32);
239 #endif
240 
241     /*
242      * For P-256, each integer MUST be encoded as 32 octets;
243      * for P-384, each integer MUST be encoded as 48 octets.
244      */
245 
246     int bn_size = dnskey_eddsa_nid_to_signature_bn_size(key->nid);
247 
248     if(FAIL(bn_size))
249     {
250         log_err("EDDSA: getting size for NID returned: %r", bn_size);
251         return FALSE;
252     }
253 
254     if((int)signature_len != bn_size)
255     {
256         log_err("EDDSA: signature size unexpected");
257         return FALSE;
258     }
259 
260     bool ret = FALSE;
261     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
262     if(ctx != NULL)
263     {
264         if(EVP_DigestSignInit(ctx, NULL, NULL, NULL, key->key.ed) == 1)
265         {
266             if(EVP_DigestVerify(ctx, signature, signature_len, digest, digest_len) == 1)
267             {
268                 ret = TRUE;
269             }
270             else
271             {
272                 ya_ssl_error();
273             }
274         }
275         else
276         {
277             ya_ssl_error();
278         }
279         EVP_MD_CTX_free(ctx);
280     }
281     else
282     {
283         ya_ssl_error();
284     }
285 
286     return ret;
287 }
288 
289 static EVP_PKEY*
dnskey_eddsa_public_load(u8 algorithm,const u8 * rdata_key,u16 rdata_key_size)290 dnskey_eddsa_public_load(u8 algorithm, const u8* rdata_key, u16 rdata_key_size)
291 {
292     EVP_PKEY *key = EVP_PKEY_new_raw_public_key(dnskey_eddsa_getnid(algorithm), NULL, rdata_key, rdata_key_size);
293     return key;
294  }
295 
296 
297 static u32
eddsa_public_store(const EVP_PKEY * eddsa,u8 * output_buffer,size_t output_buffer_size)298 eddsa_public_store(const EVP_PKEY* eddsa, u8* output_buffer, size_t output_buffer_size)
299 {
300     size_t size = output_buffer_size;
301     if(EVP_PKEY_get_raw_public_key(eddsa, output_buffer, &size) == 1)
302     {
303         return size;
304     }
305     else
306     {
307         return ERROR;
308     }
309 }
310 
311 
312 static u32
dnskey_eddsa_dnskey_public_store(const dnssec_key * key,u8 * rdata,size_t rdata_size)313 dnskey_eddsa_dnskey_public_store(const dnssec_key* key, u8* rdata, size_t rdata_size)
314 {
315     u32 len;
316 
317     SET_U16_AT(rdata[0], key->flags);
318     rdata[2] = DNSKEY_PROTOCOL_FIELD;
319     rdata[3] = key->algorithm;
320 
321     len = eddsa_public_store(key->key.ed, &rdata[4], rdata_size) + 4;
322 
323     return len;
324 }
325 
326 static u32
dnskey_eddsa_size(const dnssec_key * key)327 dnskey_eddsa_size(const dnssec_key* key)
328 {
329     size_t size = 0;
330     EVP_PKEY_get_raw_private_key(key->key.ed, NULL, &size);
331     return (u32)size * 8;
332 }
333 
334 /**
335  * Returns the size in byte of the public key.
336  *
337  * @param eddsa
338  * @return
339  */
340 
341 static u32
dnskey_eddsa_public_size(const EVP_PKEY * eddsa)342 dnskey_eddsa_public_size(const EVP_PKEY* eddsa)
343 {
344     size_t size = 0;
345     EVP_PKEY_get_raw_public_key(eddsa, NULL, &size);
346     return (u32)size;
347 }
348 
349 static u32
dnskey_eddsa_dnskey_rdatasize(const dnssec_key * key)350 dnskey_eddsa_dnskey_rdatasize(const dnssec_key* key)
351 {
352     u32 size = dnskey_eddsa_public_size(key->key.ed) + 4;
353     return size;
354 }
355 
356 static void
dnskey_eddsa_free(dnssec_key * key)357 dnskey_eddsa_free(dnssec_key* key)
358 {
359     EVP_PKEY* eddsa = key->key.ed;
360     EVP_PKEY_free(eddsa);
361 
362     key->key.ed = NULL;
363 }
364 
365 static bool
dnskey_eddsa_equals(const dnssec_key * key_a,const dnssec_key * key_b)366 dnskey_eddsa_equals(const dnssec_key *key_a, const dnssec_key *key_b)
367 {
368     if(key_a == key_b)
369     {
370         return TRUE;
371     }
372 
373     if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b))
374     {
375        if(key_a->tag != key_b->tag)
376        {
377            return FALSE;
378        }
379     }
380 
381     if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm))
382     {
383         if(strcmp(key_a->origin, key_b->origin) == 0)
384         {
385             return EVP_PKEY_cmp(key_a->key.ed, key_b->key.ed) == 1;
386         }
387     }
388 
389     return FALSE;
390 }
391 
392 static ya_result
dnskey_eddsa_print_fields(dnssec_key * key,output_stream * os)393 dnskey_eddsa_print_fields(dnssec_key *key, output_stream *os)
394 {
395     struct dnskey_eddsa yeddsa;
396     dnskey_eddsa_from_eddsa(&yeddsa, key->key.ed);
397 
398     PEM_write_PrivateKey(stdout, key->key.ed, NULL, NULL, 0, NULL, NULL);
399 
400     size_t buffer_size;
401     u8 buffer[256];
402 
403     buffer_size = sizeof(buffer);
404     EVP_PKEY_get_raw_private_key(key->key.ed, buffer, &buffer_size);
405     /*
406     format("private[%llu]=", buffer_size);
407     debug_dump_ex(buffer, buffer_size, 32, TRUE, FALSE, FALSE);
408     */
409 
410     buffer_size = sizeof(buffer);
411     EVP_PKEY_get_raw_public_key(key->key.ed, buffer, &buffer_size);
412     /*
413     format("\npublic[%llu]=", buffer_size);
414     debug_dump_ex(buffer, buffer_size, 32, TRUE, FALSE, FALSE);
415     println("");
416     flushout();
417     */
418 
419     ya_result ret = dnskey_field_access_print(ECDSA_field_access, &yeddsa, os);
420 
421     return ret;
422 }
423 
424 static const dnssec_key_vtbl eddsa_vtbl = {
425     dnskey_eddsa_signdigest,
426     dnskey_eddsa_verifydigest,
427     dnskey_eddsa_dnskey_rdatasize,
428     dnskey_eddsa_dnskey_public_store,
429     dnskey_eddsa_free,
430     dnskey_eddsa_equals,
431     dnskey_eddsa_print_fields,
432     dnskey_eddsa_size,
433     "ECDSA"
434 };
435 
436 static ya_result
dnskey_eddsa_initinstance(EVP_PKEY * eddsa,u8 algorithm,u16 flags,const char * origin,dnssec_key ** out_key)437 dnskey_eddsa_initinstance(EVP_PKEY *eddsa, u8 algorithm, u16 flags, const char *origin, dnssec_key **out_key)
438 {
439     int nid;
440     // needed to compute the tag
441     u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */
442 
443     *out_key = NULL;
444 
445     if(FAIL(nid = dnskey_eddsa_getnid(algorithm)))
446     {
447         return nid;
448     }
449 
450 #if DEBUG
451     memset(rdata, 0xff, sizeof(rdata));
452 #endif
453 
454     u32 public_key_size = dnskey_eddsa_public_size(eddsa);
455 
456     if(public_key_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES)
457     {
458         return DNSSEC_ERROR_KEYISTOOBIG;
459     }
460 
461     SET_U16_AT(rdata[0], flags); // NATIVEFLAGS
462     rdata[2] = DNSKEY_PROTOCOL_FIELD;
463     rdata[3] = algorithm;
464 
465     if(eddsa_public_store(eddsa, &rdata[4], sizeof(rdata) - 4) != public_key_size)
466     {
467         return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */
468     }
469 
470     /* Note : + 4 because of the flags,protocol & algorithm bytes
471      *        are not taken in account
472      */
473 
474     u16 tag = dnskey_get_tag_from_rdata(rdata, public_key_size + 4);
475 
476     dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC
477 
478     key->key.ed = eddsa;
479     key->vtbl = &eddsa_vtbl;
480     key->tag = tag;
481     key->nid = nid;
482     key->status |= (i2d_PrivateKey(eddsa, NULL) > 0)?DNSKEY_KEY_IS_PRIVATE:0;
483 
484     *out_key = key;
485 
486     return SUCCESS;
487 }
488 
489 static ya_result
dnskey_eddsa_parse_field(struct dnskey_field_parser * parser,parser_s * p)490 dnskey_eddsa_parse_field(struct dnskey_field_parser *parser, parser_s *p)
491 {
492     struct dnskey_eddsa *yeddsa = (struct dnskey_eddsa*)parser->data;
493 
494     ya_result ret = dnskey_field_access_parse(ECDSA_field_access, yeddsa, p);
495 
496     return ret;
497 }
498 
499 static ya_result
dnskey_eddsa_parse_set_key(struct dnskey_field_parser * parser,dnssec_key * key)500 dnskey_eddsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key)
501 {
502     struct dnskey_eddsa *yeddsa = (struct dnskey_eddsa*)parser->data;
503 
504     if(key == NULL)
505     {
506         return UNEXPECTED_NULL_ARGUMENT_ERROR;
507     }
508 
509     switch(key->algorithm)
510     {
511         case DNSKEY_ALGORITHM_ED25519:
512         case DNSKEY_ALGORITHM_ED448:
513             break;
514         default:
515             return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
516     }
517 
518     if(yeddsa->private_key.buffer == NULL)
519     {
520         return DNSSEC_ERROR_INCOMPLETEKEY;
521     }
522 
523     int nid;
524 
525     if(FAIL(nid = dnskey_eddsa_getnid(key->algorithm)))
526     {
527         return nid;
528     }
529 
530     EVP_PKEY *eddsa = EVP_PKEY_new_raw_private_key(nid, NULL, yeddsa->private_key.buffer, yeddsa->private_key.size);
531 
532     if(eddsa != NULL)
533     {
534         // at this point, yeddsa has been emptied
535 
536         u32 rdata_size = dnskey_eddsa_public_size(eddsa);
537 
538         u16 tag;
539 
540         u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES];
541 
542         if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES)
543         {
544             EVP_PKEY_free(eddsa);
545             return DNSSEC_ERROR_KEYISTOOBIG;
546         }
547 
548         SET_U16_AT(rdata[0], key->flags);
549         rdata[2] = DNSKEY_PROTOCOL_FIELD;
550         rdata[3] = key->algorithm;
551 
552         if(eddsa_public_store(eddsa, &rdata[4], sizeof(rdata) - 4) != rdata_size)
553         {
554             EVP_PKEY_free(eddsa);
555             return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */
556         }
557 
558         /* Note : + 4 because of the flags,protocol & algorithm bytes
559          *        are not taken in account
560          */
561 
562         tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4);
563 
564         key->key.ed = eddsa;
565 
566         key->tag = tag;
567         key->nid = nid;
568 
569         key->status |= DNSKEY_KEY_IS_VALID | DNSKEY_KEY_IS_PRIVATE;
570 
571         return SUCCESS;
572     }
573 
574     return DNSSEC_ERROR_INCOMPLETEKEY;
575 }
576 
577 static void
dnskey_eddsa_parse_finalize(struct dnskey_field_parser * parser)578 dnskey_eddsa_parse_finalize(struct dnskey_field_parser *parser)
579 {
580     struct dnskey_eddsa *ydsa = (struct dnskey_eddsa*)parser->data;
581 
582     if(ydsa != NULL)
583     {
584         dnskey_eddsa_finalize(ydsa);
585         ZFREE(ydsa, struct dnskey_eddsa);
586     }
587 }
588 
589 static const struct dnskey_field_parser_vtbl eddsa_field_parser_vtbl =
590 {
591     dnskey_eddsa_parse_field,
592     dnskey_eddsa_parse_set_key,
593     dnskey_eddsa_parse_finalize,
594     "EDDSA"
595 };
596 
597 void
dnskey_eddsa_parse_init(dnskey_field_parser * fp)598 dnskey_eddsa_parse_init(dnskey_field_parser *fp)
599 {
600     struct dnskey_eddsa *yeddsa;
601     ZALLOC_OBJECT_OR_DIE(yeddsa, struct dnskey_eddsa, KEYECDSA_TAG);
602     ZEROMEMORY(yeddsa, sizeof(struct dnskey_eddsa));
603     fp->data = yeddsa;
604     fp->vtbl = &eddsa_field_parser_vtbl;
605 }
606 
607 ya_result
dnskey_eddsa_loadpublic(const u8 * rdata,u16 rdata_size,const char * origin,dnssec_key ** out_key)608 dnskey_eddsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key)
609 {
610     *out_key = NULL;
611 
612     if(rdata == NULL || rdata_size <= 6 || origin == NULL)
613     {
614         /* bad */
615 
616         return UNEXPECTED_NULL_ARGUMENT_ERROR;
617     }
618 
619     u16 flags = GET_U16_AT(rdata[0]);
620     u8 algorithm = rdata[3];
621 
622     if((algorithm != DNSKEY_ALGORITHM_ECDSAP256SHA256) && (algorithm != DNSKEY_ALGORITHM_ECDSAP384SHA384) &&
623        (algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448))
624     {
625         return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
626     }
627 
628     rdata += 4;
629     rdata_size -= 4;
630 
631     ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA;
632 
633     EVP_PKEY *eddsa = dnskey_eddsa_public_load(algorithm, rdata, rdata_size);
634 
635     if(eddsa != NULL)
636     {
637         dnssec_key *key;
638 
639         if(ISOK(return_value = dnskey_eddsa_initinstance(eddsa, algorithm, flags, origin, &key)))
640         {
641             *out_key = key;
642 
643             return return_value;
644         }
645 
646         EVP_PKEY_free(eddsa);
647     }
648 
649     return return_value;
650 }
651 
652 ya_result
dnskey_eddsa_newinstance(u32 size,u8 algorithm,u16 flags,const char * origin,dnssec_key ** out_key)653 dnskey_eddsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key)
654 {
655     *out_key = NULL;
656 
657     if(size > DNSSEC_MAXIMUM_KEY_SIZE)
658     {
659         return DNSSEC_ERROR_KEYISTOOBIG;
660     }
661 
662     if((algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448))
663     {
664         return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
665     }
666 
667     ya_result ret = ERROR;
668 
669     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(dnskey_eddsa_getnid(algorithm), NULL);
670     if(ctx != NULL)
671     {
672         if(EVP_PKEY_keygen_init(ctx) == 1)
673         {
674             EVP_PKEY *evp_key = NULL;
675 
676             if(EVP_PKEY_keygen(ctx, &evp_key) == 1)
677             {
678                 dnssec_key *key = NULL;
679 
680                 if(ISOK(ret = dnskey_eddsa_initinstance(evp_key, algorithm, flags, origin, &key)))
681                 {
682                     *out_key = key;
683                 }
684             }
685         }
686 
687         if(FAIL(ret))
688         {
689             unsigned long ssl_err;
690 
691             while((ssl_err = ERR_get_error()) != 0)
692             {
693                 char buffer[256];
694                 ERR_error_string_n(ssl_err, buffer, sizeof(buffer));
695                 osformatln(termerr, "digest signature returned an ssl error %08x %s", (unsigned int)ssl_err, buffer);
696             }
697 
698             ERR_clear_error();
699         }
700 
701         EVP_PKEY_CTX_free(ctx);
702     }
703 
704     return ret;
705 }
706 #else
707 
dnskey_eddsa_not_supported()708 void dnskey_eddsa_not_supported() {}
709 
710 #endif // HAS_EDDSA_SUPPORT
711 
712 /** @} */
713 
714