1 /* $NetBSD: pkcs11ecdsa_link.c,v 1.1.1.5 2015/07/08 15:38:01 christos Exp $ */
4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
23 #if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_ECDSA)
25 #include <isc/entropy.h>
28 #include <isc/string.h>
31 #include <dns/keyvalues.h>
32 #include <dst/result.h>
34 #include "dst_internal.h"
35 #include "dst_parse.h"
36 #include "dst_pkcs11.h"
38 #include <pk11/pk11.h>
39 #include <pk11/internal.h>
40 #define WANT_ECC_CURVES
41 #include <pk11/constants.h>
43 #include <pkcs11/pkcs11.h>
46 * FIPS 186-3 ECDSA keys:
51 * CKA_EC_PARAMS (choice with OID namedCurve)
53 * object class CKO_PUBLIC_KEY
55 * attribute CKA_EC_PARAMS (choice with OID namedCurve)
56 * attribute CKA_EC_POINT (point Q)
58 * object class CKO_PRIVATE_KEY
60 * attribute CKA_EC_PARAMS (choice with OID namedCurve)
61 * attribute CKA_VALUE (big int d)
62 * point format: 0x04 (octet-string) <2*size+1> 0x4 (uncompressed) <x> <y>
65 #define TAG_OCTECT_STRING 0x04
66 #define UNCOMPRESSED 0x04
68 #define DST_RET(a) {ret = a; goto err;}
70 static CK_BBOOL truevalue
= TRUE
;
71 static CK_BBOOL falsevalue
= FALSE
;
73 static isc_result_t
pkcs11ecdsa_todns(const dst_key_t
*key
,
75 static void pkcs11ecdsa_destroy(dst_key_t
*key
);
76 static isc_result_t
pkcs11ecdsa_fetch(dst_key_t
*key
, const char *engine
,
77 const char *label
, dst_key_t
*pub
);
80 pkcs11ecdsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
82 CK_MECHANISM mech
= {0, NULL
, 0 };
84 pk11_context_t
*pk11_ctx
;
85 pk11_object_t
*ec
= key
->keydata
.pkey
;
89 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
90 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
92 if (dctx
->key
->key_alg
== DST_ALG_ECDSA256
)
93 mech
.mechanism
= CKM_SHA256
;
95 mech
.mechanism
= CKM_SHA384
;
97 pk11_ctx
= (pk11_context_t
*) isc_mem_get(dctx
->mctx
,
100 return (ISC_R_NOMEMORY
);
101 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
102 if (ec
->ontoken
&& (dctx
->use
== DO_SIGN
))
105 slotid
= pk11_get_best_token(OP_EC
);
106 ret
= pk11_get_session(pk11_ctx
, OP_EC
, ISC_TRUE
, ISC_FALSE
, ISC_FALSE
,
108 if (ret
!= ISC_R_SUCCESS
)
111 PK11_RET(pkcs_C_DigestInit
, (pk11_ctx
->session
, &mech
), ISC_R_FAILURE
);
112 dctx
->ctxdata
.pk11_ctx
= pk11_ctx
;
113 return (ISC_R_SUCCESS
);
116 pk11_return_session(pk11_ctx
);
117 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
118 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
124 pkcs11ecdsa_destroyctx(dst_context_t
*dctx
) {
125 CK_BYTE garbage
[ISC_SHA384_DIGESTLENGTH
];
126 CK_ULONG len
= ISC_SHA384_DIGESTLENGTH
;
127 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
129 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
130 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
132 if (pk11_ctx
!= NULL
) {
133 (void) pkcs_C_DigestFinal(pk11_ctx
->session
, garbage
, &len
);
134 memset(garbage
, 0, sizeof(garbage
));
135 pk11_return_session(pk11_ctx
);
136 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
137 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
138 dctx
->ctxdata
.pk11_ctx
= NULL
;
143 pkcs11ecdsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
145 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
146 isc_result_t ret
= ISC_R_SUCCESS
;
148 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
149 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
151 PK11_CALL(pkcs_C_DigestUpdate
,
153 (CK_BYTE_PTR
) data
->base
,
154 (CK_ULONG
) data
->length
),
161 pkcs11ecdsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
163 CK_MECHANISM mech
= { CKM_ECDSA
, NULL
, 0 };
164 CK_OBJECT_HANDLE hKey
= CK_INVALID_HANDLE
;
165 CK_OBJECT_CLASS keyClass
= CKO_PRIVATE_KEY
;
166 CK_KEY_TYPE keyType
= CKK_EC
;
167 CK_ATTRIBUTE keyTemplate
[] =
169 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
170 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
171 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
172 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
173 { CKA_SIGN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
174 { CKA_EC_PARAMS
, NULL
, 0 },
175 { CKA_VALUE
, NULL
, 0 }
178 CK_BYTE digest
[ISC_SHA384_DIGESTLENGTH
];
181 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
182 dst_key_t
*key
= dctx
->key
;
183 pk11_object_t
*ec
= key
->keydata
.pkey
;
185 isc_result_t ret
= ISC_R_SUCCESS
;
188 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
189 key
->key_alg
== DST_ALG_ECDSA384
);
192 if (key
->key_alg
== DST_ALG_ECDSA256
) {
193 dgstlen
= ISC_SHA256_DIGESTLENGTH
;
194 siglen
= DNS_SIG_ECDSA256SIZE
;
196 siglen
= DNS_SIG_ECDSA384SIZE
;
197 dgstlen
= ISC_SHA384_DIGESTLENGTH
;
200 PK11_RET(pkcs_C_DigestFinal
,
201 (pk11_ctx
->session
, digest
, &dgstlen
),
204 isc_buffer_availableregion(sig
, &r
);
205 if (r
.length
< siglen
)
206 DST_RET(ISC_R_NOSPACE
);
208 if (ec
->ontoken
&& (ec
->object
!= CK_INVALID_HANDLE
)) {
209 pk11_ctx
->ontoken
= ec
->ontoken
;
210 pk11_ctx
->object
= ec
->object
;
214 for (attr
= pk11_attribute_first(ec
);
216 attr
= pk11_attribute_next(ec
, attr
))
217 switch (attr
->type
) {
219 INSIST(keyTemplate
[5].type
== attr
->type
);
220 keyTemplate
[5].pValue
= isc_mem_get(dctx
->mctx
,
222 if (keyTemplate
[5].pValue
== NULL
)
223 DST_RET(ISC_R_NOMEMORY
);
224 memmove(keyTemplate
[5].pValue
, attr
->pValue
,
226 keyTemplate
[5].ulValueLen
= attr
->ulValueLen
;
229 INSIST(keyTemplate
[6].type
== attr
->type
);
230 keyTemplate
[6].pValue
= isc_mem_get(dctx
->mctx
,
232 if (keyTemplate
[6].pValue
== NULL
)
233 DST_RET(ISC_R_NOMEMORY
);
234 memmove(keyTemplate
[6].pValue
, attr
->pValue
,
236 keyTemplate
[6].ulValueLen
= attr
->ulValueLen
;
239 pk11_ctx
->object
= CK_INVALID_HANDLE
;
240 pk11_ctx
->ontoken
= ISC_FALSE
;
241 PK11_RET(pkcs_C_CreateObject
,
243 keyTemplate
, (CK_ULONG
) 7,
249 PK11_RET(pkcs_C_SignInit
,
250 (pk11_ctx
->session
, &mech
,
251 pk11_ctx
->ontoken
? pk11_ctx
->object
: hKey
),
254 PK11_RET(pkcs_C_Sign
,
257 (CK_BYTE_PTR
) r
.base
, &siglen
),
260 isc_buffer_add(sig
, (unsigned int) siglen
);
264 if (hKey
!= CK_INVALID_HANDLE
)
265 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, hKey
);
266 for (i
= 5; i
<= 6; i
++)
267 if (keyTemplate
[i
].pValue
!= NULL
) {
268 memset(keyTemplate
[i
].pValue
, 0,
269 keyTemplate
[i
].ulValueLen
);
270 isc_mem_put(dctx
->mctx
,
271 keyTemplate
[i
].pValue
,
272 keyTemplate
[i
].ulValueLen
);
274 pk11_return_session(pk11_ctx
);
275 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
276 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
277 dctx
->ctxdata
.pk11_ctx
= NULL
;
283 pkcs11ecdsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
285 CK_MECHANISM mech
= { CKM_ECDSA
, NULL
, 0 };
286 CK_OBJECT_HANDLE hKey
= CK_INVALID_HANDLE
;
287 CK_OBJECT_CLASS keyClass
= CKO_PUBLIC_KEY
;
288 CK_KEY_TYPE keyType
= CKK_EC
;
289 CK_ATTRIBUTE keyTemplate
[] =
291 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
292 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
293 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
294 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
295 { CKA_VERIFY
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
296 { CKA_EC_PARAMS
, NULL
, 0 },
297 { CKA_EC_POINT
, NULL
, 0 }
300 CK_BYTE digest
[ISC_SHA384_DIGESTLENGTH
];
302 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
303 dst_key_t
*key
= dctx
->key
;
304 pk11_object_t
*ec
= key
->keydata
.pkey
;
305 isc_result_t ret
= ISC_R_SUCCESS
;
308 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
309 key
->key_alg
== DST_ALG_ECDSA384
);
312 if (key
->key_alg
== DST_ALG_ECDSA256
)
313 dgstlen
= ISC_SHA256_DIGESTLENGTH
;
315 dgstlen
= ISC_SHA384_DIGESTLENGTH
;
317 PK11_RET(pkcs_C_DigestFinal
,
318 (pk11_ctx
->session
, digest
, &dgstlen
),
321 for (attr
= pk11_attribute_first(ec
);
323 attr
= pk11_attribute_next(ec
, attr
))
324 switch (attr
->type
) {
326 INSIST(keyTemplate
[5].type
== attr
->type
);
327 keyTemplate
[5].pValue
= isc_mem_get(dctx
->mctx
,
329 if (keyTemplate
[5].pValue
== NULL
)
330 DST_RET(ISC_R_NOMEMORY
);
331 memmove(keyTemplate
[5].pValue
, attr
->pValue
,
333 keyTemplate
[5].ulValueLen
= attr
->ulValueLen
;
336 INSIST(keyTemplate
[6].type
== attr
->type
);
337 keyTemplate
[6].pValue
= isc_mem_get(dctx
->mctx
,
339 if (keyTemplate
[6].pValue
== NULL
)
340 DST_RET(ISC_R_NOMEMORY
);
341 memmove(keyTemplate
[6].pValue
, attr
->pValue
,
343 keyTemplate
[6].ulValueLen
= attr
->ulValueLen
;
346 pk11_ctx
->object
= CK_INVALID_HANDLE
;
347 pk11_ctx
->ontoken
= ISC_FALSE
;
348 PK11_RET(pkcs_C_CreateObject
,
350 keyTemplate
, (CK_ULONG
) 7,
354 PK11_RET(pkcs_C_VerifyInit
,
355 (pk11_ctx
->session
, &mech
, hKey
),
358 PK11_RET(pkcs_C_Verify
,
361 (CK_BYTE_PTR
) sig
->base
, (CK_ULONG
) sig
->length
),
366 if (hKey
!= CK_INVALID_HANDLE
)
367 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, hKey
);
368 for (i
= 5; i
<= 6; i
++)
369 if (keyTemplate
[i
].pValue
!= NULL
) {
370 memset(keyTemplate
[i
].pValue
, 0,
371 keyTemplate
[i
].ulValueLen
);
372 isc_mem_put(dctx
->mctx
,
373 keyTemplate
[i
].pValue
,
374 keyTemplate
[i
].ulValueLen
);
376 pk11_return_session(pk11_ctx
);
377 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
378 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
379 dctx
->ctxdata
.pk11_ctx
= NULL
;
385 pkcs11ecdsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
386 pk11_object_t
*ec1
, *ec2
;
387 CK_ATTRIBUTE
*attr1
, *attr2
;
389 ec1
= key1
->keydata
.pkey
;
390 ec2
= key2
->keydata
.pkey
;
392 if ((ec1
== NULL
) && (ec2
== NULL
))
394 else if ((ec1
== NULL
) || (ec2
== NULL
))
397 attr1
= pk11_attribute_bytype(ec1
, CKA_EC_PARAMS
);
398 attr2
= pk11_attribute_bytype(ec2
, CKA_EC_PARAMS
);
399 if ((attr1
== NULL
) && (attr2
== NULL
))
401 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
402 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
403 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
406 attr1
= pk11_attribute_bytype(ec1
, CKA_EC_POINT
);
407 attr2
= pk11_attribute_bytype(ec2
, CKA_EC_POINT
);
408 if ((attr1
== NULL
) && (attr2
== NULL
))
410 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
411 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
412 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
415 attr1
= pk11_attribute_bytype(ec1
, CKA_VALUE
);
416 attr2
= pk11_attribute_bytype(ec2
, CKA_VALUE
);
417 if (((attr1
!= NULL
) || (attr2
!= NULL
)) &&
418 ((attr1
== NULL
) || (attr2
== NULL
) ||
419 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
420 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
)))
423 if (!ec1
->ontoken
&& !ec2
->ontoken
)
425 else if (ec1
->ontoken
|| ec2
->ontoken
||
426 (ec1
->object
!= ec2
->object
))
433 if (key->key_alg == DST_ALG_ECDSA256) { \
434 attr->pValue = isc_mem_get(key->mctx, \
435 sizeof(pk11_ecc_prime256v1)); \
436 if (attr->pValue == NULL) \
437 DST_RET(ISC_R_NOMEMORY); \
438 memmove(attr->pValue, \
439 pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1)); \
440 attr->ulValueLen = sizeof(pk11_ecc_prime256v1); \
442 attr->pValue = isc_mem_get(key->mctx, \
443 sizeof(pk11_ecc_secp384r1)); \
444 if (attr->pValue == NULL) \
445 DST_RET(ISC_R_NOMEMORY); \
446 memmove(attr->pValue, \
447 pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1)); \
448 attr->ulValueLen = sizeof(pk11_ecc_secp384r1); \
451 #define FREECURVE() \
452 if (attr->pValue != NULL) { \
453 memset(attr->pValue, 0, attr->ulValueLen); \
454 isc_mem_put(key->mctx, attr->pValue, attr->ulValueLen); \
455 attr->pValue = NULL; \
459 pkcs11ecdsa_generate(dst_key_t
*key
, int unused
, void (*callback
)(int)) {
461 CK_MECHANISM mech
= { CKM_EC_KEY_PAIR_GEN
, NULL
, 0 };
462 CK_OBJECT_HANDLE pub
= CK_INVALID_HANDLE
;
463 CK_OBJECT_CLASS pubClass
= CKO_PUBLIC_KEY
;
464 CK_KEY_TYPE keyType
= CKK_EC
;
465 CK_ATTRIBUTE pubTemplate
[] =
467 { CKA_CLASS
, &pubClass
, (CK_ULONG
) sizeof(pubClass
) },
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_VERIFY
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
472 { CKA_EC_PARAMS
, NULL
, 0 }
474 CK_OBJECT_HANDLE priv
= CK_INVALID_HANDLE
;
475 CK_OBJECT_HANDLE privClass
= CKO_PRIVATE_KEY
;
476 CK_ATTRIBUTE privTemplate
[] =
478 { CKA_CLASS
, &privClass
, (CK_ULONG
) sizeof(privClass
) },
479 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
480 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
481 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
482 { CKA_SENSITIVE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
483 { CKA_EXTRACTABLE
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
484 { CKA_SIGN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) }
488 pk11_context_t
*pk11_ctx
;
491 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
492 key
->key_alg
== DST_ALG_ECDSA384
);
496 pk11_ctx
= (pk11_context_t
*) isc_mem_get(key
->mctx
,
498 if (pk11_ctx
== NULL
)
499 return (ISC_R_NOMEMORY
);
500 ret
= pk11_get_session(pk11_ctx
, OP_EC
, ISC_TRUE
, ISC_FALSE
,
501 ISC_FALSE
, NULL
, pk11_get_best_token(OP_EC
));
502 if (ret
!= ISC_R_SUCCESS
)
505 ec
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*ec
));
507 DST_RET(ISC_R_NOMEMORY
);
508 memset(ec
, 0, sizeof(*ec
));
509 key
->keydata
.pkey
= ec
;
510 ec
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
) * 3);
511 if (ec
->repr
== NULL
)
512 DST_RET(ISC_R_NOMEMORY
);
513 memset(ec
->repr
, 0, sizeof(*attr
) * 3);
517 attr
[0].type
= CKA_EC_PARAMS
;
518 attr
[1].type
= CKA_EC_POINT
;
519 attr
[2].type
= CKA_VALUE
;
521 attr
= &pubTemplate
[5];
524 PK11_RET(pkcs_C_GenerateKeyPair
,
525 (pk11_ctx
->session
, &mech
,
526 pubTemplate
, (CK_ULONG
) 6,
527 privTemplate
, (CK_ULONG
) 7,
529 DST_R_CRYPTOFAILURE
);
531 attr
= &pubTemplate
[5];
538 PK11_RET(pkcs_C_GetAttributeValue
,
539 (pk11_ctx
->session
, pub
, attr
, 1),
540 DST_R_CRYPTOFAILURE
);
541 attr
->pValue
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
542 if (attr
->pValue
== NULL
)
543 DST_RET(ISC_R_NOMEMORY
);
544 memset(attr
->pValue
, 0, attr
->ulValueLen
);
545 PK11_RET(pkcs_C_GetAttributeValue
,
546 (pk11_ctx
->session
, pub
, attr
, 1),
547 DST_R_CRYPTOFAILURE
);
550 PK11_RET(pkcs_C_GetAttributeValue
,
551 (pk11_ctx
->session
, priv
, attr
, 1),
552 DST_R_CRYPTOFAILURE
);
553 attr
->pValue
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
554 if (attr
->pValue
== NULL
)
555 DST_RET(ISC_R_NOMEMORY
);
556 memset(attr
->pValue
, 0, attr
->ulValueLen
);
557 PK11_RET(pkcs_C_GetAttributeValue
,
558 (pk11_ctx
->session
, priv
, attr
, 1),
559 DST_R_CRYPTOFAILURE
);
561 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, priv
);
562 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pub
);
563 pk11_return_session(pk11_ctx
);
564 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
565 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
567 if (key
->key_alg
== DST_ALG_ECDSA256
)
568 key
->key_size
= DNS_KEY_ECDSA256SIZE
* 4;
570 key
->key_size
= DNS_KEY_ECDSA384SIZE
* 4;
572 return (ISC_R_SUCCESS
);
575 pkcs11ecdsa_destroy(key
);
576 if (priv
!= CK_INVALID_HANDLE
)
577 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, priv
);
578 if (pub
!= CK_INVALID_HANDLE
)
579 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pub
);
580 pk11_return_session(pk11_ctx
);
581 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
582 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
588 pkcs11ecdsa_isprivate(const dst_key_t
*key
) {
589 pk11_object_t
*ec
= key
->keydata
.pkey
;
594 attr
= pk11_attribute_bytype(ec
, CKA_VALUE
);
595 return (ISC_TF((attr
!= NULL
) || ec
->ontoken
));
599 pkcs11ecdsa_destroy(dst_key_t
*key
) {
600 pk11_object_t
*ec
= key
->keydata
.pkey
;
606 INSIST((ec
->object
== CK_INVALID_HANDLE
) || ec
->ontoken
);
608 for (attr
= pk11_attribute_first(ec
);
610 attr
= pk11_attribute_next(ec
, attr
))
611 switch (attr
->type
) {
620 if (ec
->repr
!= NULL
) {
621 memset(ec
->repr
, 0, ec
->attrcnt
* sizeof(*attr
));
622 isc_mem_put(key
->mctx
,
624 ec
->attrcnt
* sizeof(*attr
));
626 memset(ec
, 0, sizeof(*ec
));
627 isc_mem_put(key
->mctx
, ec
, sizeof(*ec
));
628 key
->keydata
.pkey
= NULL
;
632 pkcs11ecdsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
638 REQUIRE(key
->keydata
.pkey
!= NULL
);
640 if (key
->key_alg
== DST_ALG_ECDSA256
)
641 len
= DNS_KEY_ECDSA256SIZE
;
643 len
= DNS_KEY_ECDSA384SIZE
;
645 ec
= key
->keydata
.pkey
;
646 attr
= pk11_attribute_bytype(ec
, CKA_EC_POINT
);
647 if ((attr
== NULL
) ||
648 (attr
->ulValueLen
!= len
+ 3) ||
649 (((CK_BYTE_PTR
) attr
->pValue
)[0] != TAG_OCTECT_STRING
) ||
650 (((CK_BYTE_PTR
) attr
->pValue
)[1] != len
+ 1) ||
651 (((CK_BYTE_PTR
) attr
->pValue
)[2] != UNCOMPRESSED
))
652 return (ISC_R_FAILURE
);
654 isc_buffer_availableregion(data
, &r
);
656 return (ISC_R_NOSPACE
);
657 memmove(r
.base
, (CK_BYTE_PTR
) attr
->pValue
+ 3, len
);
658 isc_buffer_add(data
, len
);
660 return (ISC_R_SUCCESS
);
664 pkcs11ecdsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
670 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
671 key
->key_alg
== DST_ALG_ECDSA384
);
673 if (key
->key_alg
== DST_ALG_ECDSA256
)
674 len
= DNS_KEY_ECDSA256SIZE
;
676 len
= DNS_KEY_ECDSA384SIZE
;
678 isc_buffer_remainingregion(data
, &r
);
680 return (ISC_R_SUCCESS
);
682 return (DST_R_INVALIDPUBLICKEY
);
684 ec
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*ec
));
686 return (ISC_R_NOMEMORY
);
687 memset(ec
, 0, sizeof(*ec
));
688 ec
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
) * 2);
689 if (ec
->repr
== NULL
)
694 attr
->type
= CKA_EC_PARAMS
;
695 if (key
->key_alg
== DST_ALG_ECDSA256
) {
697 isc_mem_get(key
->mctx
, sizeof(pk11_ecc_prime256v1
));
698 if (attr
->pValue
== NULL
)
700 memmove(attr
->pValue
,
701 pk11_ecc_prime256v1
, sizeof(pk11_ecc_prime256v1
));
702 attr
->ulValueLen
= sizeof(pk11_ecc_prime256v1
);
705 isc_mem_get(key
->mctx
, sizeof(pk11_ecc_secp384r1
));
706 if (attr
->pValue
== NULL
)
708 memmove(attr
->pValue
,
709 pk11_ecc_secp384r1
, sizeof(pk11_ecc_secp384r1
));
710 attr
->ulValueLen
= sizeof(pk11_ecc_secp384r1
);
714 attr
->type
= CKA_EC_POINT
;
715 attr
->pValue
= isc_mem_get(key
->mctx
, len
+ 3);
716 if (attr
->pValue
== NULL
)
718 ((CK_BYTE_PTR
) attr
->pValue
)[0] = TAG_OCTECT_STRING
;
719 ((CK_BYTE_PTR
) attr
->pValue
)[1] = len
+ 1;
720 ((CK_BYTE_PTR
) attr
->pValue
)[2] = UNCOMPRESSED
;
721 memmove((CK_BYTE_PTR
) attr
->pValue
+ 3, r
.base
, len
);
722 attr
->ulValueLen
= len
+ 3;
724 isc_buffer_forward(data
, len
);
725 key
->keydata
.pkey
= ec
;
726 key
->key_size
= len
* 4;
727 return (ISC_R_SUCCESS
);
730 for (attr
= pk11_attribute_first(ec
);
732 attr
= pk11_attribute_next(ec
, attr
))
733 switch (attr
->type
) {
739 if (ec
->repr
!= NULL
) {
740 memset(ec
->repr
, 0, ec
->attrcnt
* sizeof(*attr
));
741 isc_mem_put(key
->mctx
,
743 ec
->attrcnt
* sizeof(*attr
));
745 memset(ec
, 0, sizeof(*ec
));
746 isc_mem_put(key
->mctx
, ec
, sizeof(*ec
));
747 return (ISC_R_NOMEMORY
);
751 pkcs11ecdsa_tofile(const dst_key_t
*key
, const char *directory
) {
755 unsigned char *buf
= NULL
;
759 if (key
->keydata
.pkey
== NULL
)
760 return (DST_R_NULLKEY
);
764 return (dst__privstruct_writefile(key
, &priv
, directory
));
767 ec
= key
->keydata
.pkey
;
768 attr
= pk11_attribute_bytype(ec
, CKA_VALUE
);
770 buf
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
772 return (ISC_R_NOMEMORY
);
773 priv
.elements
[i
].tag
= TAG_ECDSA_PRIVATEKEY
;
774 priv
.elements
[i
].length
= (unsigned short) attr
->ulValueLen
;
775 memmove(buf
, attr
->pValue
, attr
->ulValueLen
);
776 priv
.elements
[i
].data
= buf
;
780 if (key
->engine
!= NULL
) {
781 priv
.elements
[i
].tag
= TAG_ECDSA_ENGINE
;
782 priv
.elements
[i
].length
= strlen(key
->engine
) + 1;
783 priv
.elements
[i
].data
= (unsigned char *)key
->engine
;
787 if (key
->label
!= NULL
) {
788 priv
.elements
[i
].tag
= TAG_ECDSA_LABEL
;
789 priv
.elements
[i
].length
= strlen(key
->label
) + 1;
790 priv
.elements
[i
].data
= (unsigned char *)key
->label
;
795 ret
= dst__privstruct_writefile(key
, &priv
, directory
);
798 memset(buf
, 0, attr
->ulValueLen
);
799 isc_mem_put(key
->mctx
, buf
, attr
->ulValueLen
);
805 pkcs11ecdsa_fetch(dst_key_t
*key
, const char *engine
, const char *label
,
809 CK_OBJECT_CLASS keyClass
= CKO_PRIVATE_KEY
;
810 CK_KEY_TYPE keyType
= CKK_EC
;
811 CK_ATTRIBUTE searchTemplate
[] =
813 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
814 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
815 { CKA_TOKEN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
816 { CKA_LABEL
, NULL
, 0 }
820 CK_ATTRIBUTE
*pubattr
;
822 pk11_object_t
*pubec
;
823 pk11_context_t
*pk11_ctx
= NULL
;
827 return (DST_R_NOENGINE
);
829 ec
= key
->keydata
.pkey
;
830 pubec
= pub
->keydata
.pkey
;
832 ec
->object
= CK_INVALID_HANDLE
;
833 ec
->ontoken
= ISC_TRUE
;
834 ec
->reqlogon
= ISC_TRUE
;
835 ec
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
) * 2);
836 if (ec
->repr
== NULL
)
837 return (ISC_R_NOMEMORY
);
838 memset(ec
->repr
, 0, sizeof(*attr
) * 2);
842 attr
->type
= CKA_EC_PARAMS
;
843 pubattr
= pk11_attribute_bytype(pubec
, CKA_EC_PARAMS
);
844 attr
->pValue
= isc_mem_get(key
->mctx
, pubattr
->ulValueLen
);
845 if (attr
->pValue
== NULL
)
846 DST_RET(ISC_R_NOMEMORY
);
847 memmove(attr
->pValue
, pubattr
->pValue
, pubattr
->ulValueLen
);
848 attr
->ulValueLen
= pubattr
->ulValueLen
;
851 attr
->type
= CKA_EC_POINT
;
852 pubattr
= pk11_attribute_bytype(pubec
, CKA_EC_POINT
);
853 attr
->pValue
= isc_mem_get(key
->mctx
, pubattr
->ulValueLen
);
854 if (attr
->pValue
== NULL
)
855 DST_RET(ISC_R_NOMEMORY
);
856 memmove(attr
->pValue
, pubattr
->pValue
, pubattr
->ulValueLen
);
857 attr
->ulValueLen
= pubattr
->ulValueLen
;
859 ret
= pk11_parse_uri(ec
, label
, key
->mctx
, OP_EC
);
860 if (ret
!= ISC_R_SUCCESS
)
863 pk11_ctx
= (pk11_context_t
*) isc_mem_get(key
->mctx
,
865 if (pk11_ctx
== NULL
)
866 DST_RET(ISC_R_NOMEMORY
);
867 ret
= pk11_get_session(pk11_ctx
, OP_EC
, ISC_TRUE
, ISC_FALSE
,
868 ec
->reqlogon
, NULL
, ec
->slot
);
869 if (ret
!= ISC_R_SUCCESS
)
872 attr
= pk11_attribute_bytype(ec
, CKA_LABEL
);
874 attr
= pk11_attribute_bytype(ec
, CKA_ID
);
875 INSIST(attr
!= NULL
);
876 searchTemplate
[3].type
= CKA_ID
;
878 searchTemplate
[3].pValue
= attr
->pValue
;
879 searchTemplate
[3].ulValueLen
= attr
->ulValueLen
;
881 PK11_RET(pkcs_C_FindObjectsInit
,
882 (pk11_ctx
->session
, searchTemplate
, (CK_ULONG
) 4),
883 DST_R_CRYPTOFAILURE
);
884 PK11_RET(pkcs_C_FindObjects
,
885 (pk11_ctx
->session
, &ec
->object
, (CK_ULONG
) 1, &cnt
),
886 DST_R_CRYPTOFAILURE
);
887 (void) pkcs_C_FindObjectsFinal(pk11_ctx
->session
);
889 DST_RET(ISC_R_NOTFOUND
);
891 DST_RET(ISC_R_EXISTS
);
893 if (engine
!= NULL
) {
894 key
->engine
= isc_mem_strdup(key
->mctx
, engine
);
895 if (key
->engine
== NULL
)
896 DST_RET(ISC_R_NOMEMORY
);
899 key
->label
= isc_mem_strdup(key
->mctx
, label
);
900 if (key
->label
== NULL
)
901 DST_RET(ISC_R_NOMEMORY
);
903 pk11_return_session(pk11_ctx
);
904 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
905 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
906 return (ISC_R_SUCCESS
);
909 if (pk11_ctx
!= NULL
) {
910 pk11_return_session(pk11_ctx
);
911 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
912 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
918 pkcs11ecdsa_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
921 pk11_object_t
*ec
= NULL
;
922 CK_ATTRIBUTE
*attr
, *pattr
;
923 isc_mem_t
*mctx
= key
->mctx
;
925 const char *engine
= NULL
, *label
= NULL
;
927 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
928 key
->key_alg
== DST_ALG_ECDSA384
);
930 if ((pub
== NULL
) || (pub
->keydata
.pkey
== NULL
))
931 DST_RET(DST_R_INVALIDPRIVATEKEY
);
933 /* read private key file */
934 ret
= dst__privstruct_parse(key
, DST_ALG_ECDSA256
, lexer
, mctx
, &priv
);
935 if (ret
!= ISC_R_SUCCESS
)
939 if (priv
.nelements
!= 0)
940 DST_RET(DST_R_INVALIDPRIVATEKEY
);
942 key
->keydata
.pkey
= pub
->keydata
.pkey
;
943 pub
->keydata
.pkey
= NULL
;
944 key
->key_size
= pub
->key_size
;
946 dst__privstruct_free(&priv
, mctx
);
947 memset(&priv
, 0, sizeof(priv
));
949 return (ISC_R_SUCCESS
);
952 for (i
= 0; i
< priv
.nelements
; i
++) {
953 switch (priv
.elements
[i
].tag
) {
954 case TAG_ECDSA_ENGINE
:
955 engine
= (char *)priv
.elements
[i
].data
;
957 case TAG_ECDSA_LABEL
:
958 label
= (char *)priv
.elements
[i
].data
;
964 ec
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*ec
));
966 DST_RET(ISC_R_NOMEMORY
);
967 memset(ec
, 0, sizeof(*ec
));
968 key
->keydata
.pkey
= ec
;
970 /* Is this key is stored in a HSM? See if we can fetch it. */
971 if ((label
!= NULL
) || (engine
!= NULL
)) {
972 ret
= pkcs11ecdsa_fetch(key
, engine
, label
, pub
);
973 if (ret
!= ISC_R_SUCCESS
)
975 dst__privstruct_free(&priv
, mctx
);
976 memset(&priv
, 0, sizeof(priv
));
980 ec
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
) * 3);
981 if (ec
->repr
== NULL
)
982 DST_RET(ISC_R_NOMEMORY
);
983 memset(ec
->repr
, 0, sizeof(*attr
) * 3);
987 attr
->type
= CKA_EC_PARAMS
;
988 pattr
= pk11_attribute_bytype(pub
->keydata
.pkey
, CKA_EC_PARAMS
);
989 INSIST(pattr
!= NULL
);
990 attr
->pValue
= isc_mem_get(key
->mctx
, pattr
->ulValueLen
);
991 if (attr
->pValue
== NULL
)
992 DST_RET(ISC_R_NOMEMORY
);
993 memmove(attr
->pValue
, pattr
->pValue
, pattr
->ulValueLen
);
994 attr
->ulValueLen
= pattr
->ulValueLen
;
997 attr
->type
= CKA_EC_POINT
;
998 pattr
= pk11_attribute_bytype(pub
->keydata
.pkey
, CKA_EC_POINT
);
999 INSIST(pattr
!= NULL
);
1000 attr
->pValue
= isc_mem_get(key
->mctx
, pattr
->ulValueLen
);
1001 if (attr
->pValue
== NULL
)
1002 DST_RET(ISC_R_NOMEMORY
);
1003 memmove(attr
->pValue
, pattr
->pValue
, pattr
->ulValueLen
);
1004 attr
->ulValueLen
= pattr
->ulValueLen
;
1007 attr
->type
= CKA_VALUE
;
1008 attr
->pValue
= isc_mem_get(key
->mctx
, priv
.elements
[0].length
);
1009 if (attr
->pValue
== NULL
)
1010 DST_RET(ISC_R_NOMEMORY
);
1011 memmove(attr
->pValue
, priv
.elements
[0].data
, priv
.elements
[0].length
);
1012 attr
->ulValueLen
= priv
.elements
[0].length
;
1014 dst__privstruct_free(&priv
, mctx
);
1015 memset(&priv
, 0, sizeof(priv
));
1016 if (key
->key_alg
== DST_ALG_ECDSA256
)
1017 key
->key_size
= DNS_KEY_ECDSA256SIZE
* 4;
1019 key
->key_size
= DNS_KEY_ECDSA384SIZE
* 4;
1021 return (ISC_R_SUCCESS
);
1024 pkcs11ecdsa_destroy(key
);
1025 dst__privstruct_free(&priv
, mctx
);
1026 memset(&priv
, 0, sizeof(priv
));
1031 pkcs11ecdsa_fromlabel(dst_key_t
*key
, const char *engine
, const char *label
,
1035 CK_OBJECT_HANDLE hKey
= CK_INVALID_HANDLE
;
1036 CK_OBJECT_CLASS keyClass
= CKO_PUBLIC_KEY
;
1037 CK_KEY_TYPE keyType
= CKK_EC
;
1038 CK_ATTRIBUTE searchTemplate
[] =
1040 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
1041 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
1042 { CKA_TOKEN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
1043 { CKA_LABEL
, NULL
, 0 }
1048 pk11_context_t
*pk11_ctx
= NULL
;
1054 ec
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*ec
));
1056 return (ISC_R_NOMEMORY
);
1057 memset(ec
, 0, sizeof(*ec
));
1058 ec
->object
= CK_INVALID_HANDLE
;
1059 ec
->ontoken
= ISC_TRUE
;
1060 ec
->reqlogon
= ISC_TRUE
;
1061 key
->keydata
.pkey
= ec
;
1063 ec
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
) * 2);
1064 if (ec
->repr
== NULL
)
1065 DST_RET(ISC_R_NOMEMORY
);
1066 memset(ec
->repr
, 0, sizeof(*attr
) * 2);
1069 attr
[0].type
= CKA_EC_PARAMS
;
1070 attr
[1].type
= CKA_EC_POINT
;
1072 ret
= pk11_parse_uri(ec
, label
, key
->mctx
, OP_EC
);
1073 if (ret
!= ISC_R_SUCCESS
)
1076 pk11_ctx
= (pk11_context_t
*) isc_mem_get(key
->mctx
,
1078 if (pk11_ctx
== NULL
)
1079 DST_RET(ISC_R_NOMEMORY
);
1080 ret
= pk11_get_session(pk11_ctx
, OP_EC
, ISC_TRUE
, ISC_FALSE
,
1081 ec
->reqlogon
, NULL
, ec
->slot
);
1082 if (ret
!= ISC_R_SUCCESS
)
1085 attr
= pk11_attribute_bytype(ec
, CKA_LABEL
);
1087 attr
= pk11_attribute_bytype(ec
, CKA_ID
);
1088 INSIST(attr
!= NULL
);
1089 searchTemplate
[3].type
= CKA_ID
;
1091 searchTemplate
[3].pValue
= attr
->pValue
;
1092 searchTemplate
[3].ulValueLen
= attr
->ulValueLen
;
1094 PK11_RET(pkcs_C_FindObjectsInit
,
1095 (pk11_ctx
->session
, searchTemplate
, (CK_ULONG
) 4),
1096 DST_R_CRYPTOFAILURE
);
1097 PK11_RET(pkcs_C_FindObjects
,
1098 (pk11_ctx
->session
, &hKey
, (CK_ULONG
) 1, &cnt
),
1099 DST_R_CRYPTOFAILURE
);
1100 (void) pkcs_C_FindObjectsFinal(pk11_ctx
->session
);
1102 DST_RET(ISC_R_NOTFOUND
);
1104 DST_RET(ISC_R_EXISTS
);
1107 PK11_RET(pkcs_C_GetAttributeValue
,
1108 (pk11_ctx
->session
, hKey
, attr
, 2),
1109 DST_R_CRYPTOFAILURE
);
1110 for (i
= 0; i
<= 1; i
++) {
1111 attr
[i
].pValue
= isc_mem_get(key
->mctx
, attr
[i
].ulValueLen
);
1112 if (attr
[i
].pValue
== NULL
)
1113 DST_RET(ISC_R_NOMEMORY
);
1114 memset(attr
[i
].pValue
, 0, attr
[i
].ulValueLen
);
1116 PK11_RET(pkcs_C_GetAttributeValue
,
1117 (pk11_ctx
->session
, hKey
, attr
, 2),
1118 DST_R_CRYPTOFAILURE
);
1120 keyClass
= CKO_PRIVATE_KEY
;
1121 PK11_RET(pkcs_C_FindObjectsInit
,
1122 (pk11_ctx
->session
, searchTemplate
, (CK_ULONG
) 4),
1123 DST_R_CRYPTOFAILURE
);
1124 PK11_RET(pkcs_C_FindObjects
,
1125 (pk11_ctx
->session
, &ec
->object
, (CK_ULONG
) 1, &cnt
),
1126 DST_R_CRYPTOFAILURE
);
1127 (void) pkcs_C_FindObjectsFinal(pk11_ctx
->session
);
1129 DST_RET(ISC_R_NOTFOUND
);
1131 DST_RET(ISC_R_EXISTS
);
1133 if (engine
!= NULL
) {
1134 key
->engine
= isc_mem_strdup(key
->mctx
, engine
);
1135 if (key
->engine
== NULL
)
1136 DST_RET(ISC_R_NOMEMORY
);
1139 key
->label
= isc_mem_strdup(key
->mctx
, label
);
1140 if (key
->label
== NULL
)
1141 DST_RET(ISC_R_NOMEMORY
);
1142 if (key
->key_alg
== DST_ALG_ECDSA256
)
1143 key
->key_size
= DNS_KEY_ECDSA256SIZE
* 4;
1145 key
->key_size
= DNS_KEY_ECDSA384SIZE
* 4;
1147 pk11_return_session(pk11_ctx
);
1148 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
1149 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
1150 return (ISC_R_SUCCESS
);
1153 pkcs11ecdsa_destroy(key
);
1154 if (pk11_ctx
!= NULL
) {
1155 pk11_return_session(pk11_ctx
);
1156 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
1157 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
1162 static dst_func_t pkcs11ecdsa_functions
= {
1163 pkcs11ecdsa_createctx
,
1164 NULL
, /*%< createctx2 */
1165 pkcs11ecdsa_destroyctx
,
1166 pkcs11ecdsa_adddata
,
1169 NULL
, /*%< verify2 */
1170 NULL
, /*%< computesecret */
1171 pkcs11ecdsa_compare
,
1172 NULL
, /*%< paramcompare */
1173 pkcs11ecdsa_generate
,
1174 pkcs11ecdsa_isprivate
,
1175 pkcs11ecdsa_destroy
,
1177 pkcs11ecdsa_fromdns
,
1180 NULL
, /*%< cleanup */
1181 pkcs11ecdsa_fromlabel
,
1183 NULL
, /*%< restore */
1187 dst__pkcs11ecdsa_init(dst_func_t
**funcp
) {
1188 REQUIRE(funcp
!= NULL
);
1190 *funcp
= &pkcs11ecdsa_functions
;
1191 return (ISC_R_SUCCESS
);
1194 #else /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */
1196 #include <isc/util.h>
1198 EMPTY_TRANSLATION_UNIT
1200 #endif /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */