1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #if HAVE_OPENSSL_ED25519 || HAVE_OPENSSL_ED448
15
16 #include <stdbool.h>
17
18 #include <openssl/err.h>
19 #include <openssl/evp.h>
20 #include <openssl/objects.h>
21 #include <openssl/x509.h>
22 #if !defined(OPENSSL_NO_ENGINE)
23 #include <openssl/engine.h>
24 #endif /* if !defined(OPENSSL_NO_ENGINE) */
25
26 #include <isc/mem.h>
27 #include <isc/result.h>
28 #include <isc/safe.h>
29 #include <isc/string.h>
30 #include <isc/util.h>
31
32 #include <dns/keyvalues.h>
33
34 #include "dst_internal.h"
35 #include "dst_openssl.h"
36 #include "dst_parse.h"
37
38 #define DST_RET(a) \
39 { \
40 ret = a; \
41 goto err; \
42 }
43
44 #if HAVE_OPENSSL_ED25519
45 #ifndef NID_ED25519
46 #error "Ed25519 group is not known (NID_ED25519)"
47 #endif /* ifndef NID_ED25519 */
48 #endif /* HAVE_OPENSSL_ED25519 */
49
50 #if HAVE_OPENSSL_ED448
51 #ifndef NID_ED448
52 #error "Ed448 group is not known (NID_ED448)"
53 #endif /* ifndef NID_ED448 */
54 #endif /* HAVE_OPENSSL_ED448 */
55
56 static isc_result_t
raw_key_to_ossl(unsigned int key_alg,int private,const unsigned char * key,size_t * key_len,EVP_PKEY ** pkey)57 raw_key_to_ossl(unsigned int key_alg, int private, const unsigned char *key,
58 size_t *key_len, EVP_PKEY **pkey) {
59 isc_result_t ret;
60 int pkey_type = EVP_PKEY_NONE;
61 size_t len = 0;
62
63 #if HAVE_OPENSSL_ED25519
64 if (key_alg == DST_ALG_ED25519) {
65 pkey_type = EVP_PKEY_ED25519;
66 len = DNS_KEY_ED25519SIZE;
67 }
68 #endif /* HAVE_OPENSSL_ED25519 */
69 #if HAVE_OPENSSL_ED448
70 if (key_alg == DST_ALG_ED448) {
71 pkey_type = EVP_PKEY_ED448;
72 len = DNS_KEY_ED448SIZE;
73 }
74 #endif /* HAVE_OPENSSL_ED448 */
75 if (pkey_type == EVP_PKEY_NONE) {
76 return (ISC_R_NOTIMPLEMENTED);
77 }
78
79 ret = (private ? DST_R_INVALIDPRIVATEKEY : DST_R_INVALIDPUBLICKEY);
80 if (*key_len < len) {
81 return (ret);
82 }
83
84 if (private) {
85 *pkey = EVP_PKEY_new_raw_private_key(pkey_type, NULL, key, len);
86 } else {
87 *pkey = EVP_PKEY_new_raw_public_key(pkey_type, NULL, key, len);
88 }
89 if (*pkey == NULL) {
90 return (dst__openssl_toresult(ret));
91 }
92
93 *key_len = len;
94 return (ISC_R_SUCCESS);
95 }
96
97 static isc_result_t
98 openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
99 const char *pin);
100
101 static isc_result_t
openssleddsa_createctx(dst_key_t * key,dst_context_t * dctx)102 openssleddsa_createctx(dst_key_t *key, dst_context_t *dctx) {
103 isc_buffer_t *buf = NULL;
104
105 UNUSED(key);
106 REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
107 dctx->key->key_alg == DST_ALG_ED448);
108
109 isc_buffer_allocate(dctx->mctx, &buf, 64);
110 dctx->ctxdata.generic = buf;
111
112 return (ISC_R_SUCCESS);
113 }
114
115 static void
openssleddsa_destroyctx(dst_context_t * dctx)116 openssleddsa_destroyctx(dst_context_t *dctx) {
117 isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
118
119 REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
120 dctx->key->key_alg == DST_ALG_ED448);
121 if (buf != NULL) {
122 isc_buffer_free(&buf);
123 }
124 dctx->ctxdata.generic = NULL;
125 }
126
127 static isc_result_t
openssleddsa_adddata(dst_context_t * dctx,const isc_region_t * data)128 openssleddsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
129 isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
130 isc_buffer_t *nbuf = NULL;
131 isc_region_t r;
132 unsigned int length;
133 isc_result_t result;
134
135 REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
136 dctx->key->key_alg == DST_ALG_ED448);
137
138 result = isc_buffer_copyregion(buf, data);
139 if (result == ISC_R_SUCCESS) {
140 return (ISC_R_SUCCESS);
141 }
142
143 length = isc_buffer_length(buf) + data->length + 64;
144 isc_buffer_allocate(dctx->mctx, &nbuf, length);
145 isc_buffer_usedregion(buf, &r);
146 (void)isc_buffer_copyregion(nbuf, &r);
147 (void)isc_buffer_copyregion(nbuf, data);
148 isc_buffer_free(&buf);
149 dctx->ctxdata.generic = nbuf;
150
151 return (ISC_R_SUCCESS);
152 }
153
154 static isc_result_t
openssleddsa_sign(dst_context_t * dctx,isc_buffer_t * sig)155 openssleddsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
156 isc_result_t ret;
157 dst_key_t *key = dctx->key;
158 isc_region_t tbsreg;
159 isc_region_t sigreg;
160 EVP_PKEY *pkey = key->keydata.pkey;
161 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
162 isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
163 size_t siglen;
164
165 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
166 key->key_alg == DST_ALG_ED448);
167
168 if (ctx == NULL) {
169 return (ISC_R_NOMEMORY);
170 }
171
172 if (key->key_alg == DST_ALG_ED25519) {
173 siglen = DNS_SIG_ED25519SIZE;
174 } else {
175 siglen = DNS_SIG_ED448SIZE;
176 }
177
178 isc_buffer_availableregion(sig, &sigreg);
179 if (sigreg.length < (unsigned int)siglen) {
180 DST_RET(ISC_R_NOSPACE);
181 }
182
183 isc_buffer_usedregion(buf, &tbsreg);
184
185 if (EVP_DigestSignInit(ctx, NULL, NULL, NULL, pkey) != 1) {
186 DST_RET(dst__openssl_toresult3(
187 dctx->category, "EVP_DigestSignInit", ISC_R_FAILURE));
188 }
189 if (EVP_DigestSign(ctx, sigreg.base, &siglen, tbsreg.base,
190 tbsreg.length) != 1) {
191 DST_RET(dst__openssl_toresult3(dctx->category, "EVP_DigestSign",
192 DST_R_SIGNFAILURE));
193 }
194 isc_buffer_add(sig, (unsigned int)siglen);
195 ret = ISC_R_SUCCESS;
196
197 err:
198 EVP_MD_CTX_free(ctx);
199 isc_buffer_free(&buf);
200 dctx->ctxdata.generic = NULL;
201
202 return (ret);
203 }
204
205 static isc_result_t
openssleddsa_verify(dst_context_t * dctx,const isc_region_t * sig)206 openssleddsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
207 isc_result_t ret;
208 dst_key_t *key = dctx->key;
209 int status;
210 isc_region_t tbsreg;
211 EVP_PKEY *pkey = key->keydata.pkey;
212 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
213 isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
214 unsigned int siglen = 0;
215
216 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
217 key->key_alg == DST_ALG_ED448);
218
219 if (ctx == NULL) {
220 return (ISC_R_NOMEMORY);
221 }
222
223 #if HAVE_OPENSSL_ED25519
224 if (key->key_alg == DST_ALG_ED25519) {
225 siglen = DNS_SIG_ED25519SIZE;
226 }
227 #endif /* if HAVE_OPENSSL_ED25519 */
228 #if HAVE_OPENSSL_ED448
229 if (key->key_alg == DST_ALG_ED448) {
230 siglen = DNS_SIG_ED448SIZE;
231 }
232 #endif /* if HAVE_OPENSSL_ED448 */
233 if (siglen == 0) {
234 return (ISC_R_NOTIMPLEMENTED);
235 }
236
237 if (sig->length != siglen) {
238 return (DST_R_VERIFYFAILURE);
239 }
240
241 isc_buffer_usedregion(buf, &tbsreg);
242
243 if (EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey) != 1) {
244 DST_RET(dst__openssl_toresult3(
245 dctx->category, "EVP_DigestVerifyInit", ISC_R_FAILURE));
246 }
247
248 status = EVP_DigestVerify(ctx, sig->base, siglen, tbsreg.base,
249 tbsreg.length);
250
251 switch (status) {
252 case 1:
253 ret = ISC_R_SUCCESS;
254 break;
255 case 0:
256 ret = dst__openssl_toresult(DST_R_VERIFYFAILURE);
257 break;
258 default:
259 ret = dst__openssl_toresult3(dctx->category, "EVP_DigestVerify",
260 DST_R_VERIFYFAILURE);
261 break;
262 }
263
264 err:
265 EVP_MD_CTX_free(ctx);
266 isc_buffer_free(&buf);
267 dctx->ctxdata.generic = NULL;
268
269 return (ret);
270 }
271
272 static bool
openssleddsa_compare(const dst_key_t * key1,const dst_key_t * key2)273 openssleddsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
274 int status;
275 EVP_PKEY *pkey1 = key1->keydata.pkey;
276 EVP_PKEY *pkey2 = key2->keydata.pkey;
277
278 if (pkey1 == NULL && pkey2 == NULL) {
279 return (true);
280 } else if (pkey1 == NULL || pkey2 == NULL) {
281 return (false);
282 }
283
284 status = EVP_PKEY_cmp(pkey1, pkey2);
285 if (status == 1) {
286 return (true);
287 }
288 return (false);
289 }
290
291 static isc_result_t
openssleddsa_generate(dst_key_t * key,int unused,void (* callback)(int))292 openssleddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
293 isc_result_t ret;
294 EVP_PKEY *pkey = NULL;
295 EVP_PKEY_CTX *ctx = NULL;
296 int nid = 0, status;
297
298 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
299 key->key_alg == DST_ALG_ED448);
300 UNUSED(unused);
301 UNUSED(callback);
302
303 #if HAVE_OPENSSL_ED25519
304 if (key->key_alg == DST_ALG_ED25519) {
305 nid = NID_ED25519;
306 key->key_size = DNS_KEY_ED25519SIZE * 8;
307 }
308 #endif /* if HAVE_OPENSSL_ED25519 */
309 #if HAVE_OPENSSL_ED448
310 if (key->key_alg == DST_ALG_ED448) {
311 nid = NID_ED448;
312 key->key_size = DNS_KEY_ED448SIZE * 8;
313 }
314 #endif /* if HAVE_OPENSSL_ED448 */
315 if (nid == 0) {
316 return (ISC_R_NOTIMPLEMENTED);
317 }
318
319 ctx = EVP_PKEY_CTX_new_id(nid, NULL);
320 if (ctx == NULL) {
321 return (dst__openssl_toresult2("EVP_PKEY_CTX_new_id",
322 DST_R_OPENSSLFAILURE));
323 }
324
325 status = EVP_PKEY_keygen_init(ctx);
326 if (status != 1) {
327 DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
328 DST_R_OPENSSLFAILURE));
329 }
330
331 status = EVP_PKEY_keygen(ctx, &pkey);
332 if (status != 1) {
333 DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen",
334 DST_R_OPENSSLFAILURE));
335 }
336
337 key->keydata.pkey = pkey;
338 ret = ISC_R_SUCCESS;
339
340 err:
341 EVP_PKEY_CTX_free(ctx);
342 return (ret);
343 }
344
345 static bool
openssleddsa_isprivate(const dst_key_t * key)346 openssleddsa_isprivate(const dst_key_t *key) {
347 EVP_PKEY *pkey = key->keydata.pkey;
348 size_t len;
349
350 if (pkey == NULL) {
351 return (false);
352 }
353
354 if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) == 1 && len > 0) {
355 return (true);
356 }
357 /* can check if first error is EC_R_INVALID_PRIVATE_KEY */
358 while (ERR_get_error() != 0) {
359 /**/
360 }
361
362 return (false);
363 }
364
365 static void
openssleddsa_destroy(dst_key_t * key)366 openssleddsa_destroy(dst_key_t *key) {
367 EVP_PKEY *pkey = key->keydata.pkey;
368
369 EVP_PKEY_free(pkey);
370 key->keydata.pkey = NULL;
371 }
372
373 static isc_result_t
openssleddsa_todns(const dst_key_t * key,isc_buffer_t * data)374 openssleddsa_todns(const dst_key_t *key, isc_buffer_t *data) {
375 EVP_PKEY *pkey = key->keydata.pkey;
376 isc_region_t r;
377 size_t len;
378
379 REQUIRE(pkey != NULL);
380 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
381 key->key_alg == DST_ALG_ED448);
382
383 if (key->key_alg == DST_ALG_ED25519) {
384 len = DNS_KEY_ED25519SIZE;
385 } else {
386 len = DNS_KEY_ED448SIZE;
387 }
388
389 isc_buffer_availableregion(data, &r);
390 if (r.length < len) {
391 return (ISC_R_NOSPACE);
392 }
393
394 if (EVP_PKEY_get_raw_public_key(pkey, r.base, &len) != 1)
395 return (dst__openssl_toresult(ISC_R_FAILURE));
396
397 isc_buffer_add(data, len);
398 return (ISC_R_SUCCESS);
399 }
400
401 static isc_result_t
openssleddsa_fromdns(dst_key_t * key,isc_buffer_t * data)402 openssleddsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
403 isc_result_t ret;
404 isc_region_t r;
405 size_t len;
406 EVP_PKEY *pkey;
407
408 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
409 key->key_alg == DST_ALG_ED448);
410
411 isc_buffer_remainingregion(data, &r);
412 if (r.length == 0) {
413 return (ISC_R_SUCCESS);
414 }
415
416 len = r.length;
417 ret = raw_key_to_ossl(key->key_alg, 0, r.base, &len, &pkey);
418 if (ret != ISC_R_SUCCESS)
419 return ret;
420
421 isc_buffer_forward(data, len);
422 key->keydata.pkey = pkey;
423 key->key_size = len * 8;
424 return (ISC_R_SUCCESS);
425 }
426
427 static isc_result_t
openssleddsa_tofile(const dst_key_t * key,const char * directory)428 openssleddsa_tofile(const dst_key_t *key, const char *directory) {
429 isc_result_t ret;
430 dst_private_t priv;
431 unsigned char *buf = NULL;
432 size_t len;
433 int i;
434
435 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
436 key->key_alg == DST_ALG_ED448);
437
438 if (key->keydata.pkey == NULL) {
439 return (DST_R_NULLKEY);
440 }
441
442 if (key->external) {
443 priv.nelements = 0;
444 return (dst__privstruct_writefile(key, &priv, directory));
445 }
446
447 i = 0;
448
449 if (openssleddsa_isprivate(key)) {
450 if (key->key_alg == DST_ALG_ED25519) {
451 len = DNS_KEY_ED25519SIZE;
452 } else {
453 len = DNS_KEY_ED448SIZE;
454 }
455 buf = isc_mem_get(key->mctx, len);
456 if (EVP_PKEY_get_raw_private_key(key->keydata.pkey, buf,
457 &len) != 1)
458 DST_RET(dst__openssl_toresult(ISC_R_FAILURE));
459 priv.elements[i].tag = TAG_EDDSA_PRIVATEKEY;
460 priv.elements[i].length = len;
461 priv.elements[i].data = buf;
462 i++;
463 }
464 if (key->engine != NULL) {
465 priv.elements[i].tag = TAG_EDDSA_ENGINE;
466 priv.elements[i].length = (unsigned short)strlen(key->engine) +
467 1;
468 priv.elements[i].data = (unsigned char *)key->engine;
469 i++;
470 }
471 if (key->label != NULL) {
472 priv.elements[i].tag = TAG_EDDSA_LABEL;
473 priv.elements[i].length = (unsigned short)strlen(key->label) +
474 1;
475 priv.elements[i].data = (unsigned char *)key->label;
476 i++;
477 }
478
479 priv.nelements = i;
480 ret = dst__privstruct_writefile(key, &priv, directory);
481
482 err:
483 if (buf != NULL) {
484 isc_mem_put(key->mctx, buf, len);
485 }
486 return (ret);
487 }
488
489 static isc_result_t
eddsa_check(EVP_PKEY * pkey,EVP_PKEY * pubpkey)490 eddsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) {
491 if (pubpkey == NULL) {
492 return (ISC_R_SUCCESS);
493 }
494 if (EVP_PKEY_cmp(pkey, pubpkey) == 1) {
495 return (ISC_R_SUCCESS);
496 }
497 return (ISC_R_FAILURE);
498 }
499
500 static isc_result_t
openssleddsa_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)501 openssleddsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
502 dst_private_t priv;
503 isc_result_t ret;
504 int i, privkey_index = -1;
505 const char *engine = NULL, *label = NULL;
506 EVP_PKEY *pkey = NULL, *pubpkey = NULL;
507 size_t len;
508 isc_mem_t *mctx = key->mctx;
509
510 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
511 key->key_alg == DST_ALG_ED448);
512
513 /* read private key file */
514 ret = dst__privstruct_parse(key, DST_ALG_ED25519, lexer, mctx, &priv);
515 if (ret != ISC_R_SUCCESS) {
516 goto err;
517 }
518
519 if (key->external) {
520 if (priv.nelements != 0) {
521 DST_RET(DST_R_INVALIDPRIVATEKEY);
522 }
523 if (pub == NULL) {
524 DST_RET(DST_R_INVALIDPRIVATEKEY);
525 }
526 key->keydata.pkey = pub->keydata.pkey;
527 pub->keydata.pkey = NULL;
528 dst__privstruct_free(&priv, mctx);
529 isc_safe_memwipe(&priv, sizeof(priv));
530 return (ISC_R_SUCCESS);
531 }
532
533 if (pub != NULL) {
534 pubpkey = pub->keydata.pkey;
535 }
536
537 for (i = 0; i < priv.nelements; i++) {
538 switch (priv.elements[i].tag) {
539 case TAG_EDDSA_ENGINE:
540 engine = (char *)priv.elements[i].data;
541 break;
542 case TAG_EDDSA_LABEL:
543 label = (char *)priv.elements[i].data;
544 break;
545 case TAG_EDDSA_PRIVATEKEY:
546 privkey_index = i;
547 break;
548 default:
549 break;
550 }
551 }
552
553 if (label != NULL) {
554 ret = openssleddsa_fromlabel(key, engine, label, NULL);
555 if (ret != ISC_R_SUCCESS) {
556 goto err;
557 }
558 if (eddsa_check(key->keydata.pkey, pubpkey) != ISC_R_SUCCESS) {
559 DST_RET(DST_R_INVALIDPRIVATEKEY);
560 }
561 DST_RET(ISC_R_SUCCESS);
562 }
563
564 if (privkey_index < 0) {
565 DST_RET(DST_R_INVALIDPRIVATEKEY);
566 }
567
568 len = priv.elements[privkey_index].length;
569 ret = raw_key_to_ossl(key->key_alg, 1,
570 priv.elements[privkey_index].data, &len, &pkey);
571 if (ret != ISC_R_SUCCESS) {
572 goto err;
573 }
574 if (eddsa_check(pkey, pubpkey) != ISC_R_SUCCESS) {
575 EVP_PKEY_free(pkey);
576 DST_RET(DST_R_INVALIDPRIVATEKEY);
577 }
578 key->keydata.pkey = pkey;
579 key->key_size = len * 8;
580 ret = ISC_R_SUCCESS;
581
582 err:
583 dst__privstruct_free(&priv, mctx);
584 isc_safe_memwipe(&priv, sizeof(priv));
585 return (ret);
586 }
587
588 static isc_result_t
openssleddsa_fromlabel(dst_key_t * key,const char * engine,const char * label,const char * pin)589 openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
590 const char *pin) {
591 #if !defined(OPENSSL_NO_ENGINE)
592 isc_result_t ret;
593 ENGINE *e;
594 EVP_PKEY *pkey = NULL, *pubpkey = NULL;
595 int baseid = EVP_PKEY_NONE;
596
597 UNUSED(pin);
598
599 REQUIRE(key->key_alg == DST_ALG_ED25519 ||
600 key->key_alg == DST_ALG_ED448);
601
602 #if HAVE_OPENSSL_ED25519
603 if (key->key_alg == DST_ALG_ED25519) {
604 baseid = EVP_PKEY_ED25519;
605 }
606 #endif /* if HAVE_OPENSSL_ED25519 */
607 #if HAVE_OPENSSL_ED448
608 if (key->key_alg == DST_ALG_ED448) {
609 baseid = EVP_PKEY_ED448;
610 }
611 #endif /* if HAVE_OPENSSL_ED448 */
612 if (baseid == EVP_PKEY_NONE) {
613 return (ISC_R_NOTIMPLEMENTED);
614 }
615
616 if (engine == NULL) {
617 return (DST_R_NOENGINE);
618 }
619 e = dst__openssl_getengine(engine);
620 if (e == NULL) {
621 return (DST_R_NOENGINE);
622 }
623 pkey = ENGINE_load_private_key(e, label, NULL, NULL);
624 if (pkey == NULL) {
625 return (dst__openssl_toresult2("ENGINE_load_private_key",
626 ISC_R_NOTFOUND));
627 }
628 if (EVP_PKEY_base_id(pkey) != baseid) {
629 DST_RET(DST_R_INVALIDPRIVATEKEY);
630 }
631
632 pubpkey = ENGINE_load_public_key(e, label, NULL, NULL);
633 if (eddsa_check(pkey, pubpkey) != ISC_R_SUCCESS) {
634 DST_RET(DST_R_INVALIDPRIVATEKEY);
635 }
636
637 key->engine = isc_mem_strdup(key->mctx, engine);
638 key->label = isc_mem_strdup(key->mctx, label);
639 key->key_size = EVP_PKEY_bits(pkey);
640 key->keydata.pkey = pkey;
641 pkey = NULL;
642 ret = ISC_R_SUCCESS;
643
644 err:
645 if (pubpkey != NULL) {
646 EVP_PKEY_free(pubpkey);
647 }
648 if (pkey != NULL) {
649 EVP_PKEY_free(pkey);
650 }
651 return (ret);
652 #else /* if !defined(OPENSSL_NO_ENGINE) */
653 UNUSED(key);
654 UNUSED(engine);
655 UNUSED(label);
656 UNUSED(pin);
657 return (DST_R_NOENGINE);
658 #endif /* if !defined(OPENSSL_NO_ENGINE) */
659 }
660
661 static dst_func_t openssleddsa_functions = {
662 openssleddsa_createctx,
663 NULL, /*%< createctx2 */
664 openssleddsa_destroyctx,
665 openssleddsa_adddata,
666 openssleddsa_sign,
667 openssleddsa_verify,
668 NULL, /*%< verify2 */
669 NULL, /*%< computesecret */
670 openssleddsa_compare,
671 NULL, /*%< paramcompare */
672 openssleddsa_generate,
673 openssleddsa_isprivate,
674 openssleddsa_destroy,
675 openssleddsa_todns,
676 openssleddsa_fromdns,
677 openssleddsa_tofile,
678 openssleddsa_parse,
679 NULL, /*%< cleanup */
680 openssleddsa_fromlabel,
681 NULL, /*%< dump */
682 NULL, /*%< restore */
683 };
684
685 isc_result_t
dst__openssleddsa_init(dst_func_t ** funcp)686 dst__openssleddsa_init(dst_func_t **funcp) {
687 REQUIRE(funcp != NULL);
688 if (*funcp == NULL) {
689 *funcp = &openssleddsa_functions;
690 }
691 return (ISC_R_SUCCESS);
692 }
693
694 #endif /* HAVE_OPENSSL_ED25519 || HAVE_OPENSSL_ED448 */
695