"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/openssleddsa_link.c" (4 Sep 2020, 16070 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "openssleddsa_link.c" see the Fossies "Dox" file reference documentation.

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