"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/pkcs11eddsa_link.c" (7 Sep 2020, 32297 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


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 "pkcs11eddsa_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 #include <config.h>
   13 
   14 #if defined(PKCS11CRYPTO) && \
   15     defined(HAVE_PKCS11_ED25519) || defined(HAVE_PKCS11_ED448)
   16 
   17 #include <stdbool.h>
   18 
   19 #include <isc/entropy.h>
   20 #include <isc/mem.h>
   21 #include <isc/safe.h>
   22 #include <isc/sha2.h>
   23 #include <isc/string.h>
   24 #include <isc/util.h>
   25 
   26 #include <dns/keyvalues.h>
   27 #include <dst/result.h>
   28 
   29 #include "dst_internal.h"
   30 #include "dst_parse.h"
   31 #include "dst_pkcs11.h"
   32 
   33 #include <pk11/pk11.h>
   34 #include <pk11/internal.h>
   35 #define WANT_ECC_CURVES
   36 #include <pk11/constants.h>
   37 
   38 #include <pkcs11/pkcs11.h>
   39 #include <pkcs11/eddsa.h>
   40 
   41 /*
   42  * FIPS 186-3 EDDSA keys:
   43  *  mechanisms:
   44  *    CKM_EDDSA,
   45  *    CKM_EDDSA_KEY_PAIR_GEN
   46  *  domain parameters:
   47  *    CKA_EC_PARAMS (choice with OID namedCurve)
   48  *  public keys:
   49  *    object class CKO_PUBLIC_KEY
   50  *    key type CKK_EDDSA
   51  *    attribute CKA_EC_PARAMS (choice with OID namedCurve)
   52  *    attribute CKA_EC_POINT (big int A, CKA_VALUE on the token)
   53  *  private keys:
   54  *    object class CKO_PRIVATE_KEY
   55  *    key type CKK_EDDSA
   56  *    attribute CKA_EC_PARAMS (choice with OID namedCurve)
   57  *    attribute CKA_VALUE (big int k)
   58  */
   59 
   60 #define DST_RET(a) {ret = a; goto err;}
   61 
   62 static CK_BBOOL truevalue = TRUE;
   63 static CK_BBOOL falsevalue = FALSE;
   64 
   65 static isc_result_t pkcs11eddsa_todns(const dst_key_t *key,
   66                       isc_buffer_t *data);
   67 static void pkcs11eddsa_destroy(dst_key_t *key);
   68 static isc_result_t pkcs11eddsa_fetch(dst_key_t *key, const char *engine,
   69                       const char *label, dst_key_t *pub);
   70 
   71 static isc_result_t
   72 pkcs11eddsa_createctx(dst_key_t *key, dst_context_t *dctx) {
   73     isc_buffer_t *buf = NULL;
   74     isc_result_t result;
   75 
   76     UNUSED(key);
   77     REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
   78         dctx->key->key_alg == DST_ALG_ED448);
   79 
   80     result = isc_buffer_allocate(dctx->mctx, &buf, 16);
   81     isc_buffer_setautorealloc(buf, true);
   82     dctx->ctxdata.generic = buf;
   83 
   84     return (result);
   85 }
   86 
   87 static void
   88 pkcs11eddsa_destroyctx(dst_context_t *dctx) {
   89     isc_buffer_t *buf = (isc_buffer_t *) dctx->ctxdata.generic;
   90 
   91     REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
   92         dctx->key->key_alg == DST_ALG_ED448);
   93     if (buf != NULL)
   94         isc_buffer_free(&buf);
   95     dctx->ctxdata.generic = NULL;
   96 }
   97 
   98 static isc_result_t
   99 pkcs11eddsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
  100     isc_buffer_t *buf = (isc_buffer_t *) dctx->ctxdata.generic;
  101     isc_buffer_t *nbuf = NULL;
  102     isc_region_t r;
  103     unsigned int length;
  104     isc_result_t result;
  105 
  106     REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
  107         dctx->key->key_alg == DST_ALG_ED448);
  108 
  109     result = isc_buffer_copyregion(buf, data);
  110     if (result == ISC_R_SUCCESS)
  111         return (ISC_R_SUCCESS);
  112 
  113     length = isc_buffer_length(buf) + data->length + 64;
  114     result = isc_buffer_allocate(dctx->mctx, &nbuf, length);
  115     if (result != ISC_R_SUCCESS)
  116         return (result);
  117     isc_buffer_usedregion(buf, &r);
  118     (void) isc_buffer_copyregion(nbuf, &r);
  119     (void) isc_buffer_copyregion(nbuf, data);
  120     isc_buffer_free(&buf);
  121     dctx->ctxdata.generic = nbuf;
  122 
  123     return (ISC_R_SUCCESS);
  124 }
  125 
  126 static isc_result_t
  127 pkcs11eddsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  128     isc_buffer_t *buf = (isc_buffer_t *) dctx->ctxdata.generic;
  129     CK_RV rv;
  130     CK_MECHANISM mech = { CKM_EDDSA, NULL, 0 };
  131     CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
  132     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
  133     CK_KEY_TYPE keyType = CKK_EDDSA;
  134     CK_ATTRIBUTE keyTemplate[] =
  135     {
  136         { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
  137         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
  138         { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  139         { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  140         { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
  141         { CKA_EC_PARAMS, NULL, 0 },
  142         { CKA_VALUE, NULL, 0 }
  143     };
  144     CK_ATTRIBUTE *attr;
  145     CK_ULONG siglen;
  146     CK_SLOT_ID slotid;
  147     pk11_context_t *pk11_ctx;
  148     dst_key_t *key = dctx->key;
  149     pk11_object_t *ec = key->keydata.pkey;
  150     isc_region_t t;
  151     isc_region_t r;
  152     isc_result_t ret = ISC_R_SUCCESS;
  153     unsigned int i;
  154 
  155     REQUIRE(key->key_alg == DST_ALG_ED25519 ||
  156         key->key_alg == DST_ALG_ED448);
  157     REQUIRE(ec != NULL);
  158 
  159     if (key->key_alg == DST_ALG_ED25519)
  160         siglen = DNS_SIG_ED25519SIZE;
  161     else
  162         siglen = DNS_SIG_ED448SIZE;
  163 
  164     pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
  165                           sizeof(*pk11_ctx));
  166     if (pk11_ctx == NULL)
  167         return (ISC_R_NOMEMORY);
  168     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  169     if (ec->ontoken && (dctx->use == DO_SIGN))
  170         slotid = ec->slot;
  171     else
  172         slotid = pk11_get_best_token(OP_EC);
  173     ret = pk11_get_session(pk11_ctx, OP_EC, true, false,
  174                    ec->reqlogon, NULL, slotid);
  175     if (ret != ISC_R_SUCCESS)
  176         goto err;
  177 
  178     isc_buffer_availableregion(sig, &r);
  179     if (r.length < siglen)
  180         DST_RET(ISC_R_NOSPACE);
  181 
  182     if (ec->ontoken && (ec->object != CK_INVALID_HANDLE)) {
  183         pk11_ctx->ontoken = ec->ontoken;
  184         pk11_ctx->object = ec->object;
  185         goto token_key;
  186     }
  187 
  188     for (attr = pk11_attribute_first(ec);
  189          attr != NULL;
  190          attr = pk11_attribute_next(ec, attr))
  191         switch (attr->type) {
  192         case CKA_EC_PARAMS:
  193             INSIST(keyTemplate[5].type == attr->type);
  194             keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
  195                                 attr->ulValueLen);
  196             if (keyTemplate[5].pValue == NULL)
  197                 DST_RET(ISC_R_NOMEMORY);
  198             memmove(keyTemplate[5].pValue, attr->pValue,
  199                 attr->ulValueLen);
  200             keyTemplate[5].ulValueLen = attr->ulValueLen;
  201             break;
  202         case CKA_VALUE:
  203             INSIST(keyTemplate[6].type == attr->type);
  204             keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
  205                                 attr->ulValueLen);
  206             if (keyTemplate[6].pValue == NULL)
  207                 DST_RET(ISC_R_NOMEMORY);
  208             memmove(keyTemplate[6].pValue, attr->pValue,
  209                 attr->ulValueLen);
  210             keyTemplate[6].ulValueLen = attr->ulValueLen;
  211             break;
  212         }
  213     pk11_ctx->object = CK_INVALID_HANDLE;
  214     pk11_ctx->ontoken = false;
  215     PK11_RET(pkcs_C_CreateObject,
  216          (pk11_ctx->session,
  217           keyTemplate, (CK_ULONG) 7,
  218           &hKey),
  219          ISC_R_FAILURE);
  220 
  221  token_key:
  222 
  223     PK11_RET(pkcs_C_SignInit,
  224          (pk11_ctx->session, &mech,
  225           pk11_ctx->ontoken ? pk11_ctx->object : hKey),
  226          ISC_R_FAILURE);
  227 
  228     isc_buffer_usedregion(buf, &t);
  229 
  230     PK11_RET(pkcs_C_Sign,
  231          (pk11_ctx->session,
  232           (CK_BYTE_PTR) t.base, (CK_ULONG) t.length,
  233           (CK_BYTE_PTR) r.base, &siglen),
  234          DST_R_SIGNFAILURE);
  235 
  236     isc_buffer_add(sig, (unsigned int) siglen);
  237 
  238  err:
  239 
  240     if (hKey != CK_INVALID_HANDLE)
  241         (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
  242     for (i = 5; i <= 6; i++)
  243         if (keyTemplate[i].pValue != NULL) {
  244             memset(keyTemplate[i].pValue, 0,
  245                    keyTemplate[i].ulValueLen);
  246             isc_mem_put(dctx->mctx,
  247                     keyTemplate[i].pValue,
  248                     keyTemplate[i].ulValueLen);
  249         }
  250     pk11_return_session(pk11_ctx);
  251     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  252     isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
  253     isc_buffer_free(&buf);
  254     dctx->ctxdata.generic = NULL;
  255 
  256     return (ret);
  257 }
  258 
  259 static isc_result_t
  260 pkcs11eddsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
  261     isc_buffer_t *buf = (isc_buffer_t *) dctx->ctxdata.generic;
  262     CK_RV rv;
  263     CK_MECHANISM mech = { CKM_EDDSA, NULL, 0 };
  264     CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
  265     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
  266     CK_KEY_TYPE keyType = CKK_EDDSA;
  267     CK_ATTRIBUTE keyTemplate[] =
  268     {
  269         { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
  270         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
  271         { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  272         { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  273         { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
  274         { CKA_EC_PARAMS, NULL, 0 },
  275         { CKA_VALUE, NULL, 0 }
  276     };
  277     CK_ATTRIBUTE *attr;
  278     CK_SLOT_ID slotid;
  279     pk11_context_t *pk11_ctx;
  280     dst_key_t *key = dctx->key;
  281     pk11_object_t *ec = key->keydata.pkey;
  282     isc_region_t t;
  283     isc_result_t ret = ISC_R_SUCCESS;
  284     unsigned int i;
  285 
  286     REQUIRE(key->key_alg == DST_ALG_ED25519 ||
  287         key->key_alg == DST_ALG_ED448);
  288     REQUIRE(ec != NULL);
  289 
  290     pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
  291                           sizeof(*pk11_ctx));
  292     if (pk11_ctx == NULL)
  293         return (ISC_R_NOMEMORY);
  294     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  295     if (ec->ontoken && (dctx->use == DO_SIGN))
  296         slotid = ec->slot;
  297     else
  298         slotid = pk11_get_best_token(OP_EC);
  299     ret = pk11_get_session(pk11_ctx, OP_EC, true, false,
  300                    ec->reqlogon, NULL, slotid);
  301     if (ret != ISC_R_SUCCESS)
  302         goto err;
  303 
  304     for (attr = pk11_attribute_first(ec);
  305          attr != NULL;
  306          attr = pk11_attribute_next(ec, attr))
  307         switch (attr->type) {
  308         case CKA_EC_PARAMS:
  309             INSIST(keyTemplate[5].type == attr->type);
  310             keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
  311                                 attr->ulValueLen);
  312             if (keyTemplate[5].pValue == NULL)
  313                 DST_RET(ISC_R_NOMEMORY);
  314             memmove(keyTemplate[5].pValue, attr->pValue,
  315                 attr->ulValueLen);
  316             keyTemplate[5].ulValueLen = attr->ulValueLen;
  317             break;
  318         case CKA_EC_POINT:
  319             /* keyTemplate[6].type is CKA_VALUE */
  320             keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
  321                                 attr->ulValueLen);
  322             if (keyTemplate[6].pValue == NULL)
  323                 DST_RET(ISC_R_NOMEMORY);
  324             memmove(keyTemplate[6].pValue, attr->pValue,
  325                 attr->ulValueLen);
  326             keyTemplate[6].ulValueLen = attr->ulValueLen;
  327             break;
  328         }
  329     pk11_ctx->object = CK_INVALID_HANDLE;
  330     pk11_ctx->ontoken = false;
  331     PK11_RET(pkcs_C_CreateObject,
  332          (pk11_ctx->session,
  333           keyTemplate, (CK_ULONG) 7,
  334           &hKey),
  335          ISC_R_FAILURE);
  336 
  337     PK11_RET(pkcs_C_VerifyInit,
  338          (pk11_ctx->session, &mech, hKey),
  339          ISC_R_FAILURE);
  340 
  341     isc_buffer_usedregion(buf, &t);
  342 
  343     PK11_RET(pkcs_C_Verify,
  344          (pk11_ctx->session,
  345           (CK_BYTE_PTR) t.base, (CK_ULONG) t.length,
  346           (CK_BYTE_PTR) sig->base, (CK_ULONG) sig->length),
  347          DST_R_VERIFYFAILURE);
  348 
  349  err:
  350 
  351     if (hKey != CK_INVALID_HANDLE)
  352         (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
  353     for (i = 5; i <= 6; i++)
  354         if (keyTemplate[i].pValue != NULL) {
  355             memset(keyTemplate[i].pValue, 0,
  356                    keyTemplate[i].ulValueLen);
  357             isc_mem_put(dctx->mctx,
  358                     keyTemplate[i].pValue,
  359                     keyTemplate[i].ulValueLen);
  360         }
  361     pk11_return_session(pk11_ctx);
  362     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  363     isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
  364     isc_buffer_free(&buf);
  365     dctx->ctxdata.generic = NULL;
  366 
  367     return (ret);
  368 }
  369 
  370 static bool
  371 pkcs11eddsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
  372     pk11_object_t *ec1, *ec2;
  373     CK_ATTRIBUTE *attr1, *attr2;
  374 
  375     ec1 = key1->keydata.pkey;
  376     ec2 = key2->keydata.pkey;
  377 
  378     if ((ec1 == NULL) && (ec2 == NULL))
  379         return (true);
  380     else if ((ec1 == NULL) || (ec2 == NULL))
  381         return (false);
  382 
  383     attr1 = pk11_attribute_bytype(ec1, CKA_EC_PARAMS);
  384     attr2 = pk11_attribute_bytype(ec2, CKA_EC_PARAMS);
  385     if ((attr1 == NULL) && (attr2 == NULL))
  386         return (true);
  387     else if ((attr1 == NULL) || (attr2 == NULL) ||
  388          (attr1->ulValueLen != attr2->ulValueLen) ||
  389          !isc_safe_memequal(attr1->pValue, attr2->pValue,
  390                     attr1->ulValueLen))
  391         return (false);
  392 
  393     attr1 = pk11_attribute_bytype(ec1, CKA_EC_POINT);
  394     attr2 = pk11_attribute_bytype(ec2, CKA_EC_POINT);
  395     if ((attr1 == NULL) && (attr2 == NULL))
  396         return (true);
  397     else if ((attr1 == NULL) || (attr2 == NULL) ||
  398          (attr1->ulValueLen != attr2->ulValueLen) ||
  399          !isc_safe_memequal(attr1->pValue, attr2->pValue,
  400                     attr1->ulValueLen))
  401         return (false);
  402 
  403     attr1 = pk11_attribute_bytype(ec1, CKA_VALUE);
  404     attr2 = pk11_attribute_bytype(ec2, CKA_VALUE);
  405     if (((attr1 != NULL) || (attr2 != NULL)) &&
  406         ((attr1 == NULL) || (attr2 == NULL) ||
  407          (attr1->ulValueLen != attr2->ulValueLen) ||
  408          !isc_safe_memequal(attr1->pValue, attr2->pValue,
  409                 attr1->ulValueLen)))
  410         return (false);
  411 
  412     if (!ec1->ontoken && !ec2->ontoken)
  413         return (true);
  414     else if (ec1->ontoken || ec2->ontoken ||
  415          (ec1->object != ec2->object))
  416         return (false);
  417 
  418     return (true);
  419 }
  420 
  421 #define SETCURVE() \
  422     if (key->key_alg == DST_ALG_ED25519) { \
  423         attr->pValue = isc_mem_get(key->mctx, \
  424                        sizeof(pk11_ecc_ed25519)); \
  425         if (attr->pValue == NULL) \
  426             DST_RET(ISC_R_NOMEMORY); \
  427         memmove(attr->pValue, \
  428             pk11_ecc_ed25519, sizeof(pk11_ecc_ed25519)); \
  429         attr->ulValueLen = sizeof(pk11_ecc_ed25519); \
  430     } else { \
  431         attr->pValue = isc_mem_get(key->mctx, \
  432                        sizeof(pk11_ecc_ed448)); \
  433         if (attr->pValue == NULL) \
  434             DST_RET(ISC_R_NOMEMORY); \
  435         memmove(attr->pValue, \
  436             pk11_ecc_ed448, sizeof(pk11_ecc_ed448)); \
  437         attr->ulValueLen = sizeof(pk11_ecc_ed448); \
  438     }
  439 
  440 #define FREECURVE() \
  441     if (attr->pValue != NULL) { \
  442         memset(attr->pValue, 0, attr->ulValueLen); \
  443         isc_mem_put(key->mctx, attr->pValue, attr->ulValueLen); \
  444         attr->pValue = NULL; \
  445     }
  446 
  447 static isc_result_t
  448 pkcs11eddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
  449     CK_RV rv;
  450     CK_MECHANISM mech = { CKM_EDDSA_KEY_PAIR_GEN, NULL, 0 };
  451     CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
  452     CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
  453     CK_KEY_TYPE  keyType = CKK_EDDSA;
  454     CK_ATTRIBUTE pubTemplate[] =
  455     {
  456         { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
  457         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
  458         { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  459         { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  460         { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
  461         { CKA_EC_PARAMS, NULL, 0 }
  462     };
  463     CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
  464     CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
  465     CK_ATTRIBUTE privTemplate[] =
  466     {
  467         { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
  468         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
  469         { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  470         { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  471         { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
  472         { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
  473         { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }
  474     };
  475     CK_ATTRIBUTE *attr;
  476     pk11_object_t *ec;
  477     pk11_context_t *pk11_ctx;
  478     isc_result_t ret;
  479 
  480     REQUIRE(key->key_alg == DST_ALG_ED25519 ||
  481         key->key_alg == DST_ALG_ED448);
  482     UNUSED(unused);
  483     UNUSED(callback);
  484 
  485     pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
  486                           sizeof(*pk11_ctx));
  487     if (pk11_ctx == NULL)
  488         return (ISC_R_NOMEMORY);
  489     ret = pk11_get_session(pk11_ctx, OP_EC, true, false,
  490                    false, NULL, pk11_get_best_token(OP_EC));
  491     if (ret != ISC_R_SUCCESS)
  492         goto err;
  493 
  494     ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
  495     if (ec == NULL)
  496         DST_RET(ISC_R_NOMEMORY);
  497     memset(ec, 0, sizeof(*ec));
  498     key->keydata.pkey = ec;
  499     ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
  500     if (ec->repr == NULL)
  501         DST_RET(ISC_R_NOMEMORY);
  502     memset(ec->repr, 0, sizeof(*attr) * 3);
  503     ec->attrcnt = 3;
  504 
  505     attr = ec->repr;
  506     attr[0].type = CKA_EC_PARAMS;
  507     attr[1].type = CKA_VALUE;
  508     attr[2].type = CKA_VALUE;
  509 
  510     attr = &pubTemplate[5];
  511     SETCURVE();
  512 
  513     PK11_RET(pkcs_C_GenerateKeyPair,
  514          (pk11_ctx->session, &mech,
  515           pubTemplate, (CK_ULONG) 6,
  516           privTemplate, (CK_ULONG) 7,
  517           &pub, &priv),
  518          DST_R_CRYPTOFAILURE);
  519 
  520     attr = &pubTemplate[5];
  521     FREECURVE();
  522 
  523     attr = ec->repr;
  524     SETCURVE();
  525 
  526     attr++;
  527     PK11_RET(pkcs_C_GetAttributeValue,
  528          (pk11_ctx->session, pub, attr, 1),
  529          DST_R_CRYPTOFAILURE);
  530     attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
  531     if (attr->pValue == NULL)
  532         DST_RET(ISC_R_NOMEMORY);
  533     memset(attr->pValue, 0, attr->ulValueLen);
  534     PK11_RET(pkcs_C_GetAttributeValue,
  535          (pk11_ctx->session, pub, attr, 1),
  536          DST_R_CRYPTOFAILURE);
  537     attr->type = CKA_EC_POINT;
  538 
  539     attr++;
  540     PK11_RET(pkcs_C_GetAttributeValue,
  541          (pk11_ctx->session, priv, attr, 1),
  542          DST_R_CRYPTOFAILURE);
  543     attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
  544     if (attr->pValue == NULL)
  545         DST_RET(ISC_R_NOMEMORY);
  546     memset(attr->pValue, 0, attr->ulValueLen);
  547     PK11_RET(pkcs_C_GetAttributeValue,
  548          (pk11_ctx->session, priv, attr, 1),
  549          DST_R_CRYPTOFAILURE);
  550 
  551     (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
  552     (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
  553     pk11_return_session(pk11_ctx);
  554     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  555     isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
  556 
  557     if (key->key_alg == DST_ALG_ED25519)
  558         key->key_size = DNS_KEY_ED25519SIZE;
  559     else
  560         key->key_size = DNS_KEY_ED448SIZE;
  561 
  562     return (ISC_R_SUCCESS);
  563 
  564  err:
  565     pkcs11eddsa_destroy(key);
  566     if (priv != CK_INVALID_HANDLE)
  567         (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
  568     if (pub != CK_INVALID_HANDLE)
  569         (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
  570     pk11_return_session(pk11_ctx);
  571     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  572     isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
  573 
  574     return (ret);
  575 }
  576 
  577 static bool
  578 pkcs11eddsa_isprivate(const dst_key_t *key) {
  579     pk11_object_t *ec = key->keydata.pkey;
  580     CK_ATTRIBUTE *attr;
  581 
  582     if (ec == NULL)
  583         return (false);
  584     attr = pk11_attribute_bytype(ec, CKA_VALUE);
  585     return (attr != NULL || ec->ontoken);
  586 }
  587 
  588 static void
  589 pkcs11eddsa_destroy(dst_key_t *key) {
  590     pk11_object_t *ec = key->keydata.pkey;
  591     CK_ATTRIBUTE *attr;
  592 
  593     if (ec == NULL)
  594         return;
  595 
  596     INSIST((ec->object == CK_INVALID_HANDLE) || ec->ontoken);
  597 
  598     for (attr = pk11_attribute_first(ec);
  599          attr != NULL;
  600          attr = pk11_attribute_next(ec, attr))
  601         switch (attr->type) {
  602         case CKA_LABEL:
  603         case CKA_ID:
  604         case CKA_EC_PARAMS:
  605         case CKA_EC_POINT:
  606         case CKA_VALUE:
  607             FREECURVE();
  608             break;
  609         }
  610     if (ec->repr != NULL) {
  611         memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
  612         isc_mem_put(key->mctx,
  613                 ec->repr,
  614                 ec->attrcnt * sizeof(*attr));
  615     }
  616     memset(ec, 0, sizeof(*ec));
  617     isc_mem_put(key->mctx, ec, sizeof(*ec));
  618     key->keydata.pkey = NULL;
  619 }
  620 
  621 static isc_result_t
  622 pkcs11eddsa_todns(const dst_key_t *key, isc_buffer_t *data) {
  623     pk11_object_t *ec;
  624     isc_region_t r;
  625     unsigned int len;
  626     CK_ATTRIBUTE *attr;
  627 
  628     REQUIRE(key->keydata.pkey != NULL);
  629 
  630     if (key->key_alg == DST_ALG_ED25519)
  631         len = DNS_KEY_ED25519SIZE;
  632     else
  633         len = DNS_KEY_ED448SIZE;
  634 
  635     ec = key->keydata.pkey;
  636     attr = pk11_attribute_bytype(ec, CKA_EC_POINT);
  637     if ((attr == NULL) || (attr->ulValueLen != len))
  638         return (ISC_R_FAILURE);
  639 
  640     isc_buffer_availableregion(data, &r);
  641     if (r.length < len)
  642         return (ISC_R_NOSPACE);
  643     memmove(r.base, (CK_BYTE_PTR) attr->pValue, len);
  644     isc_buffer_add(data, len);
  645 
  646     return (ISC_R_SUCCESS);
  647 }
  648 
  649 static isc_result_t
  650 pkcs11eddsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
  651     pk11_object_t *ec;
  652     isc_region_t r;
  653     unsigned int len;
  654     CK_ATTRIBUTE *attr;
  655 
  656     REQUIRE(key->key_alg == DST_ALG_ED25519 ||
  657         key->key_alg == DST_ALG_ED448);
  658 
  659     if (key->key_alg == DST_ALG_ED25519)
  660         len = DNS_KEY_ED25519SIZE;
  661     else
  662         len = DNS_KEY_ED448SIZE;
  663 
  664     isc_buffer_remainingregion(data, &r);
  665     if (r.length == 0)
  666         return (ISC_R_SUCCESS);
  667     if (r.length != len)
  668         return (DST_R_INVALIDPUBLICKEY);
  669 
  670     ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
  671     if (ec == NULL)
  672         return (ISC_R_NOMEMORY);
  673     memset(ec, 0, sizeof(*ec));
  674     ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
  675     if (ec->repr == NULL)
  676         goto nomemory;
  677     ec->attrcnt = 2;
  678 
  679     attr = ec->repr;
  680     attr->type = CKA_EC_PARAMS;
  681     if (key->key_alg == DST_ALG_ED25519) {
  682         attr->pValue =
  683             isc_mem_get(key->mctx, sizeof(pk11_ecc_ed25519));
  684         if (attr->pValue == NULL)
  685             goto nomemory;
  686         memmove(attr->pValue,
  687             pk11_ecc_ed25519, sizeof(pk11_ecc_ed25519));
  688         attr->ulValueLen = sizeof(pk11_ecc_ed25519);
  689     } else {
  690         attr->pValue =
  691             isc_mem_get(key->mctx, sizeof(pk11_ecc_ed448));
  692         if (attr->pValue == NULL)
  693             goto nomemory;
  694         memmove(attr->pValue,
  695             pk11_ecc_ed448, sizeof(pk11_ecc_ed448));
  696         attr->ulValueLen = sizeof(pk11_ecc_ed448);
  697     }
  698 
  699     attr++;
  700     attr->type = CKA_EC_POINT;
  701     attr->pValue = isc_mem_get(key->mctx, len);
  702     if (attr->pValue == NULL)
  703         goto nomemory;
  704     memmove((CK_BYTE_PTR) attr->pValue, r.base, len);
  705     attr->ulValueLen = len;
  706 
  707     isc_buffer_forward(data, len);
  708     key->keydata.pkey = ec;
  709     key->key_size = len;
  710     return (ISC_R_SUCCESS);
  711 
  712  nomemory:
  713     for (attr = pk11_attribute_first(ec);
  714          attr != NULL;
  715          attr = pk11_attribute_next(ec, attr))
  716         switch (attr->type) {
  717         case CKA_EC_PARAMS:
  718         case CKA_EC_POINT:
  719             FREECURVE();
  720             break;
  721         }
  722     if (ec->repr != NULL) {
  723         memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
  724         isc_mem_put(key->mctx,
  725                 ec->repr,
  726                 ec->attrcnt * sizeof(*attr));
  727     }
  728     memset(ec, 0, sizeof(*ec));
  729     isc_mem_put(key->mctx, ec, sizeof(*ec));
  730     return (ISC_R_NOMEMORY);
  731 }
  732 
  733 static isc_result_t
  734 pkcs11eddsa_tofile(const dst_key_t *key, const char *directory) {
  735     isc_result_t ret;
  736     pk11_object_t *ec;
  737     dst_private_t priv;
  738     unsigned char *buf = NULL;
  739     unsigned int i = 0;
  740     CK_ATTRIBUTE *attr;
  741 
  742     if (key->keydata.pkey == NULL)
  743         return (DST_R_NULLKEY);
  744 
  745     if (key->external) {
  746         priv.nelements = 0;
  747         return (dst__privstruct_writefile(key, &priv, directory));
  748     }
  749 
  750     ec = key->keydata.pkey;
  751     attr = pk11_attribute_bytype(ec, CKA_VALUE);
  752     if (attr != NULL) {
  753         buf = isc_mem_get(key->mctx, attr->ulValueLen);
  754         if (buf == NULL)
  755             return (ISC_R_NOMEMORY);
  756         priv.elements[i].tag = TAG_EDDSA_PRIVATEKEY;
  757         priv.elements[i].length = (unsigned short) attr->ulValueLen;
  758         memmove(buf, attr->pValue, attr->ulValueLen);
  759         priv.elements[i].data = buf;
  760         i++;
  761     }
  762 
  763     if (key->engine != NULL) {
  764         priv.elements[i].tag = TAG_EDDSA_ENGINE;
  765         priv.elements[i].length = strlen(key->engine) + 1;
  766         priv.elements[i].data = (unsigned char *)key->engine;
  767         i++;
  768     }
  769 
  770     if (key->label != NULL) {
  771         priv.elements[i].tag = TAG_EDDSA_LABEL;
  772         priv.elements[i].length = strlen(key->label) + 1;
  773         priv.elements[i].data = (unsigned char *)key->label;
  774         i++;
  775     }
  776 
  777     priv.nelements = i;
  778     ret = dst__privstruct_writefile(key, &priv, directory);
  779 
  780     if (buf != NULL) {
  781         memset(buf, 0, attr->ulValueLen);
  782         isc_mem_put(key->mctx, buf, attr->ulValueLen);
  783     }
  784     return (ret);
  785 }
  786 
  787 static isc_result_t
  788 pkcs11eddsa_fetch(dst_key_t *key, const char *engine, const char *label,
  789           dst_key_t *pub)
  790 {
  791     CK_RV rv;
  792     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
  793     CK_KEY_TYPE keyType = CKK_EDDSA;
  794     CK_ATTRIBUTE searchTemplate[] =
  795     {
  796         { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
  797         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
  798         { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
  799         { CKA_LABEL, NULL, 0 }
  800     };
  801     CK_ULONG cnt;
  802     CK_ATTRIBUTE *attr;
  803     CK_ATTRIBUTE *pubattr;
  804     pk11_object_t *ec;
  805     pk11_object_t *pubec;
  806     pk11_context_t *pk11_ctx = NULL;
  807     isc_result_t ret;
  808 
  809     if (label == NULL)
  810         return (DST_R_NOENGINE);
  811 
  812     ec = key->keydata.pkey;
  813     pubec = pub->keydata.pkey;
  814 
  815     ec->object = CK_INVALID_HANDLE;
  816     ec->ontoken = true;
  817     ec->reqlogon = true;
  818     ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
  819     if (ec->repr == NULL)
  820         return (ISC_R_NOMEMORY);
  821     memset(ec->repr, 0, sizeof(*attr) * 2);
  822     ec->attrcnt = 2;
  823     attr = ec->repr;
  824 
  825     attr->type = CKA_EC_PARAMS;
  826     pubattr = pk11_attribute_bytype(pubec, CKA_EC_PARAMS);
  827     attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
  828     if (attr->pValue == NULL)
  829         DST_RET(ISC_R_NOMEMORY);
  830     memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
  831     attr->ulValueLen = pubattr->ulValueLen;
  832     attr++;
  833 
  834     attr->type = CKA_EC_POINT;
  835     pubattr = pk11_attribute_bytype(pubec, CKA_EC_POINT);
  836     attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
  837     if (attr->pValue == NULL)
  838         DST_RET(ISC_R_NOMEMORY);
  839     memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
  840     attr->ulValueLen = pubattr->ulValueLen;
  841 
  842     ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
  843     if (ret != ISC_R_SUCCESS)
  844         goto err;
  845 
  846     pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
  847                           sizeof(*pk11_ctx));
  848     if (pk11_ctx == NULL)
  849         DST_RET(ISC_R_NOMEMORY);
  850     ret = pk11_get_session(pk11_ctx, OP_EC, true, false,
  851                    ec->reqlogon, NULL, ec->slot);
  852     if (ret != ISC_R_SUCCESS)
  853         goto err;
  854 
  855     attr = pk11_attribute_bytype(ec, CKA_LABEL);
  856     if (attr == NULL) {
  857         attr = pk11_attribute_bytype(ec, CKA_ID);
  858         INSIST(attr != NULL);
  859         searchTemplate[3].type = CKA_ID;
  860     }
  861     searchTemplate[3].pValue = attr->pValue;
  862     searchTemplate[3].ulValueLen = attr->ulValueLen;
  863 
  864     PK11_RET(pkcs_C_FindObjectsInit,
  865          (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
  866          DST_R_CRYPTOFAILURE);
  867     PK11_RET(pkcs_C_FindObjects,
  868          (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
  869          DST_R_CRYPTOFAILURE);
  870     (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
  871     if (cnt == 0)
  872         DST_RET(ISC_R_NOTFOUND);
  873     if (cnt > 1)
  874         DST_RET(ISC_R_EXISTS);
  875 
  876     if (engine != NULL) {
  877         key->engine = isc_mem_strdup(key->mctx, engine);
  878         if (key->engine == NULL)
  879             DST_RET(ISC_R_NOMEMORY);
  880     }
  881 
  882     key->label = isc_mem_strdup(key->mctx, label);
  883     if (key->label == NULL)
  884         DST_RET(ISC_R_NOMEMORY);
  885 
  886     pk11_return_session(pk11_ctx);
  887     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  888     isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
  889     return (ISC_R_SUCCESS);
  890 
  891  err:
  892     if (pk11_ctx != NULL) {
  893         pk11_return_session(pk11_ctx);
  894         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
  895         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
  896     }
  897     return (ret);
  898 }
  899 
  900 static isc_result_t
  901 pkcs11eddsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  902     dst_private_t priv;
  903     isc_result_t ret;
  904     pk11_object_t *ec = NULL;
  905     CK_ATTRIBUTE *attr, *pattr;
  906     isc_mem_t *mctx = key->mctx;
  907     unsigned int i;
  908     const char *engine = NULL, *label = NULL;
  909 
  910     REQUIRE(key->key_alg == DST_ALG_ED25519 ||
  911         key->key_alg == DST_ALG_ED448);
  912 
  913     if ((pub == NULL) || (pub->keydata.pkey == NULL))
  914         DST_RET(DST_R_INVALIDPRIVATEKEY);
  915 
  916     /* read private key file */
  917     ret = dst__privstruct_parse(key, DST_ALG_ED25519, lexer, mctx, &priv);
  918     if (ret != ISC_R_SUCCESS)
  919         return (ret);
  920 
  921     if (key->external) {
  922         if (priv.nelements != 0)
  923             DST_RET(DST_R_INVALIDPRIVATEKEY);
  924 
  925         key->keydata.pkey = pub->keydata.pkey;
  926         pub->keydata.pkey = NULL;
  927         key->key_size = pub->key_size;
  928 
  929         dst__privstruct_free(&priv, mctx);
  930         memset(&priv, 0, sizeof(priv));
  931 
  932         return (ISC_R_SUCCESS);
  933     }
  934 
  935     for (i = 0; i < priv.nelements; i++) {
  936         switch (priv.elements[i].tag) {
  937         case TAG_EDDSA_ENGINE:
  938             engine = (char *)priv.elements[i].data;
  939             break;
  940         case TAG_EDDSA_LABEL:
  941             label = (char *)priv.elements[i].data;
  942             break;
  943         default:
  944             break;
  945         }
  946     }
  947     ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
  948     if (ec == NULL)
  949         DST_RET(ISC_R_NOMEMORY);
  950     memset(ec, 0, sizeof(*ec));
  951     key->keydata.pkey = ec;
  952 
  953     /* Is this key is stored in a HSM? See if we can fetch it. */
  954     if ((label != NULL) || (engine != NULL)) {
  955         ret = pkcs11eddsa_fetch(key, engine, label, pub);
  956         if (ret != ISC_R_SUCCESS)
  957             goto err;
  958         dst__privstruct_free(&priv, mctx);
  959         memset(&priv, 0, sizeof(priv));
  960         return (ret);
  961     }
  962 
  963     ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
  964     if (ec->repr == NULL)
  965         DST_RET(ISC_R_NOMEMORY);
  966     memset(ec->repr, 0, sizeof(*attr) * 3);
  967     ec->attrcnt = 3;
  968 
  969     attr = ec->repr;
  970     attr->type = CKA_EC_PARAMS;
  971     pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS);
  972     INSIST(pattr != NULL);
  973     attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
  974     if (attr->pValue == NULL)
  975         DST_RET(ISC_R_NOMEMORY);
  976     memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
  977     attr->ulValueLen = pattr->ulValueLen;
  978 
  979     attr++;
  980     attr->type = CKA_EC_POINT;
  981     pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT);
  982     INSIST(pattr != NULL);
  983     attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
  984     if (attr->pValue == NULL)
  985         DST_RET(ISC_R_NOMEMORY);
  986     memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
  987     attr->ulValueLen = pattr->ulValueLen;
  988 
  989     attr++;
  990     attr->type = CKA_VALUE;
  991     attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
  992     if (attr->pValue == NULL)
  993         DST_RET(ISC_R_NOMEMORY);
  994     memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length);
  995     attr->ulValueLen = priv.elements[0].length;
  996 
  997     dst__privstruct_free(&priv, mctx);
  998     memset(&priv, 0, sizeof(priv));
  999     if (key->key_alg == DST_ALG_ED25519)
 1000         key->key_size = DNS_KEY_ED25519SIZE;
 1001     else
 1002         key->key_size = DNS_KEY_ED448SIZE;
 1003 
 1004     return (ISC_R_SUCCESS);
 1005 
 1006  err:
 1007     pkcs11eddsa_destroy(key);
 1008     dst__privstruct_free(&priv, mctx);
 1009     memset(&priv, 0, sizeof(priv));
 1010     return (ret);
 1011 }
 1012 
 1013 static isc_result_t
 1014 pkcs11eddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
 1015               const char *pin)
 1016 {
 1017     CK_RV rv;
 1018     CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
 1019     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
 1020     CK_KEY_TYPE keyType = CKK_EDDSA;
 1021     CK_ATTRIBUTE searchTemplate[] =
 1022     {
 1023         { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
 1024         { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
 1025         { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
 1026         { CKA_LABEL, NULL, 0 }
 1027     };
 1028     CK_ULONG cnt;
 1029     CK_ATTRIBUTE *attr;
 1030     pk11_object_t *ec;
 1031     pk11_context_t *pk11_ctx = NULL;
 1032     isc_result_t ret;
 1033     unsigned int i;
 1034 
 1035     UNUSED(pin);
 1036 
 1037     ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
 1038     if (ec == NULL)
 1039         return (ISC_R_NOMEMORY);
 1040     memset(ec, 0, sizeof(*ec));
 1041     ec->object = CK_INVALID_HANDLE;
 1042     ec->ontoken = true;
 1043     ec->reqlogon = true;
 1044     key->keydata.pkey = ec;
 1045 
 1046     ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
 1047     if (ec->repr == NULL)
 1048         DST_RET(ISC_R_NOMEMORY);
 1049     memset(ec->repr, 0, sizeof(*attr) * 2);
 1050     ec->attrcnt = 2;
 1051     attr = ec->repr;
 1052     attr[0].type = CKA_EC_PARAMS;
 1053     attr[1].type = CKA_VALUE;
 1054 
 1055     ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
 1056     if (ret != ISC_R_SUCCESS)
 1057         goto err;
 1058 
 1059     pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
 1060                           sizeof(*pk11_ctx));
 1061     if (pk11_ctx == NULL)
 1062         DST_RET(ISC_R_NOMEMORY);
 1063     ret = pk11_get_session(pk11_ctx, OP_EC, true, false,
 1064                    ec->reqlogon, NULL, ec->slot);
 1065     if (ret != ISC_R_SUCCESS)
 1066         goto err;
 1067 
 1068     attr = pk11_attribute_bytype(ec, CKA_LABEL);
 1069     if (attr == NULL) {
 1070         attr = pk11_attribute_bytype(ec, CKA_ID);
 1071         INSIST(attr != NULL);
 1072         searchTemplate[3].type = CKA_ID;
 1073     }
 1074     searchTemplate[3].pValue = attr->pValue;
 1075     searchTemplate[3].ulValueLen = attr->ulValueLen;
 1076 
 1077     PK11_RET(pkcs_C_FindObjectsInit,
 1078          (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
 1079          DST_R_CRYPTOFAILURE);
 1080     PK11_RET(pkcs_C_FindObjects,
 1081          (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
 1082          DST_R_CRYPTOFAILURE);
 1083     (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
 1084     if (cnt == 0)
 1085         DST_RET(ISC_R_NOTFOUND);
 1086     if (cnt > 1)
 1087         DST_RET(ISC_R_EXISTS);
 1088 
 1089     attr = ec->repr;
 1090     PK11_RET(pkcs_C_GetAttributeValue,
 1091          (pk11_ctx->session, hKey, attr, 2),
 1092          DST_R_CRYPTOFAILURE);
 1093     for (i = 0; i <= 1; i++) {
 1094         attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
 1095         if (attr[i].pValue == NULL)
 1096             DST_RET(ISC_R_NOMEMORY);
 1097         memset(attr[i].pValue, 0, attr[i].ulValueLen);
 1098     }
 1099     PK11_RET(pkcs_C_GetAttributeValue,
 1100          (pk11_ctx->session, hKey, attr, 2),
 1101          DST_R_CRYPTOFAILURE);
 1102     attr[1].type = CKA_EC_POINT;
 1103 
 1104     keyClass = CKO_PRIVATE_KEY;
 1105     PK11_RET(pkcs_C_FindObjectsInit,
 1106          (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
 1107          DST_R_CRYPTOFAILURE);
 1108     PK11_RET(pkcs_C_FindObjects,
 1109          (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
 1110          DST_R_CRYPTOFAILURE);
 1111     (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
 1112     if (cnt == 0)
 1113         DST_RET(ISC_R_NOTFOUND);
 1114     if (cnt > 1)
 1115         DST_RET(ISC_R_EXISTS);
 1116 
 1117     if (engine != NULL) {
 1118         key->engine = isc_mem_strdup(key->mctx, engine);
 1119         if (key->engine == NULL)
 1120             DST_RET(ISC_R_NOMEMORY);
 1121     }
 1122 
 1123     key->label = isc_mem_strdup(key->mctx, label);
 1124     if (key->label == NULL)
 1125         DST_RET(ISC_R_NOMEMORY);
 1126     if (key->key_alg == DST_ALG_ED25519)
 1127         key->key_size = DNS_KEY_ED25519SIZE;
 1128     else
 1129         key->key_size = DNS_KEY_ED448SIZE;
 1130 
 1131     pk11_return_session(pk11_ctx);
 1132     memset(pk11_ctx, 0, sizeof(*pk11_ctx));
 1133     isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
 1134     return (ISC_R_SUCCESS);
 1135 
 1136  err:
 1137     pkcs11eddsa_destroy(key);
 1138     if (pk11_ctx != NULL) {
 1139         pk11_return_session(pk11_ctx);
 1140         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
 1141         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
 1142     }
 1143     return (ret);
 1144 }
 1145 
 1146 static dst_func_t pkcs11eddsa_functions = {
 1147     pkcs11eddsa_createctx,
 1148     NULL, /*%< createctx2 */
 1149     pkcs11eddsa_destroyctx,
 1150     pkcs11eddsa_adddata,
 1151     pkcs11eddsa_sign,
 1152     pkcs11eddsa_verify,
 1153     NULL, /*%< verify2 */
 1154     NULL, /*%< computesecret */
 1155     pkcs11eddsa_compare,
 1156     NULL, /*%< paramcompare */
 1157     pkcs11eddsa_generate,
 1158     pkcs11eddsa_isprivate,
 1159     pkcs11eddsa_destroy,
 1160     pkcs11eddsa_todns,
 1161     pkcs11eddsa_fromdns,
 1162     pkcs11eddsa_tofile,
 1163     pkcs11eddsa_parse,
 1164     NULL, /*%< cleanup */
 1165     pkcs11eddsa_fromlabel,
 1166     NULL, /*%< dump */
 1167     NULL, /*%< restore */
 1168 };
 1169 
 1170 isc_result_t
 1171 dst__pkcs11eddsa_init(dst_func_t **funcp) {
 1172     REQUIRE(funcp != NULL);
 1173     if (*funcp == NULL)
 1174         *funcp = &pkcs11eddsa_functions;
 1175     return (ISC_R_SUCCESS);
 1176 }
 1177 
 1178 #else /* PKCS11CRYPTO && HAVE_PKCS11_EDxxx */
 1179 
 1180 #include <isc/util.h>
 1181 
 1182 EMPTY_TRANSLATION_UNIT
 1183 
 1184 #endif /* PKCS11CRYPTO && HAVE_PKCS11_EDxxx */
 1185 /*! \file */