1 /* $NetBSD: pkcs11dh_link.c,v 1.1.1.5 2015/09/03 07:21:36 christos Exp $ */
2
3 /*
4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
5 *
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.
9 *
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.
17 */
18
19 #ifdef PKCS11CRYPTO
20
21 #include <config.h>
22
23 #include <ctype.h>
24
25 #include <isc/mem.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
28
29 #include <dst/result.h>
30
31 #include "dst_internal.h"
32 #include "dst_parse.h"
33 #include "dst_pkcs11.h"
34
35 #include <pk11/pk11.h>
36 #include <pk11/internal.h>
37 #define WANT_DH_PRIMES
38 #include <pk11/constants.h>
39
40 #include <pkcs11/pkcs11.h>
41
42 /*
43 * PKCS#3 DH keys:
44 * mechanisms:
45 * CKM_DH_PKCS_PARAMETER_GEN,
46 * CKM_DH_PKCS_KEY_PAIR_GEN,
47 * CKM_DH_PKCS_DERIVE
48 * domain parameters:
49 * object class CKO_DOMAIN_PARAMETERS
50 * key type CKK_DH
51 * attribute CKA_PRIME (prime p)
52 * attribute CKA_BASE (base g)
53 * optional attribute CKA_PRIME_BITS (p length in bits)
54 * public key:
55 * object class CKO_PUBLIC_KEY
56 * key type CKK_DH
57 * attribute CKA_PRIME (prime p)
58 * attribute CKA_BASE (base g)
59 * attribute CKA_VALUE (public value y)
60 * private key:
61 * object class CKO_PRIVATE_KEY
62 * key type CKK_DH
63 * attribute CKA_PRIME (prime p)
64 * attribute CKA_BASE (base g)
65 * attribute CKA_VALUE (private value x)
66 * optional attribute CKA_VALUE_BITS (x length in bits)
67 * reuse CKA_PRIVATE_EXPONENT for key pair private value
68 */
69
70 #define CKA_VALUE2 CKA_PRIVATE_EXPONENT
71
72 static CK_BBOOL truevalue = TRUE;
73 static CK_BBOOL falsevalue = FALSE;
74
75 #define DST_RET(a) {ret = a; goto err;}
76
77 static void pkcs11dh_destroy(dst_key_t *key);
78 static isc_result_t pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data);
79
80 static isc_result_t
pkcs11dh_loadpriv(const dst_key_t * key,CK_SESSION_HANDLE session,CK_OBJECT_HANDLE * hKey)81 pkcs11dh_loadpriv(const dst_key_t *key,
82 CK_SESSION_HANDLE session,
83 CK_OBJECT_HANDLE *hKey)
84 {
85 CK_RV rv;
86 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
87 CK_KEY_TYPE keyType = CKK_DH;
88 CK_ATTRIBUTE keyTemplate[] =
89 {
90 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
91 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
92 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
93 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
94 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
95 { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
96 { CKA_PRIME, NULL, 0 },
97 { CKA_BASE, NULL, 0 },
98 { CKA_VALUE, NULL, 0 }
99 };
100 CK_ATTRIBUTE *attr;
101 const pk11_object_t *priv;
102 isc_result_t ret;
103 unsigned int i;
104
105 priv = key->keydata.pkey;
106 if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
107 *hKey = priv->object;
108 return (ISC_R_SUCCESS);
109 }
110
111 attr = pk11_attribute_bytype(priv, CKA_PRIME);
112 if (attr == NULL)
113 return (DST_R_INVALIDPRIVATEKEY);
114 keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
115 if (keyTemplate[6].pValue == NULL)
116 DST_RET(ISC_R_NOMEMORY);
117 memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen);
118 keyTemplate[6].ulValueLen = attr->ulValueLen;
119
120 attr = pk11_attribute_bytype(priv, CKA_BASE);
121 if (attr == NULL)
122 DST_RET(DST_R_INVALIDPRIVATEKEY);
123 keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
124 if (keyTemplate[7].pValue == NULL)
125 DST_RET(ISC_R_NOMEMORY);
126 memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen);
127 keyTemplate[7].ulValueLen = attr->ulValueLen;
128
129 attr = pk11_attribute_bytype(priv, CKA_VALUE2);
130 if (attr == NULL)
131 DST_RET(DST_R_INVALIDPRIVATEKEY);
132 keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
133 if (keyTemplate[8].pValue == NULL)
134 DST_RET(ISC_R_NOMEMORY);
135 memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen);
136 keyTemplate[8].ulValueLen = attr->ulValueLen;
137
138 PK11_CALL(pkcs_C_CreateObject,
139 (session, keyTemplate, (CK_ULONG) 9, hKey),
140 DST_R_COMPUTESECRETFAILURE);
141 if (rv == CKR_OK)
142 ret = ISC_R_SUCCESS;
143
144 err:
145 for (i = 6; i <= 8; i++)
146 if (keyTemplate[i].pValue != NULL) {
147 memset(keyTemplate[i].pValue, 0,
148 keyTemplate[i].ulValueLen);
149 isc_mem_put(key->mctx,
150 keyTemplate[i].pValue,
151 keyTemplate[i].ulValueLen);
152 }
153 return (ret);
154 }
155
156 static isc_result_t
pkcs11dh_computesecret(const dst_key_t * pub,const dst_key_t * priv,isc_buffer_t * secret)157 pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
158 isc_buffer_t *secret)
159 {
160 CK_RV rv;
161 CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 };
162 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
163 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
164 CK_OBJECT_HANDLE hDerived = CK_INVALID_HANDLE;
165 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
166 CK_ATTRIBUTE *attr;
167 CK_ULONG secLen;
168 CK_ATTRIBUTE keyTemplate[] =
169 {
170 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
171 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
172 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
173 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
174 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
175 { CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) }
176 };
177 CK_ATTRIBUTE valTemplate[] =
178 {
179 { CKA_VALUE, NULL, 0 }
180 };
181 CK_BYTE *secValue;
182 pk11_context_t ctx;
183 isc_result_t ret;
184 unsigned int i;
185 isc_region_t r;
186
187 REQUIRE(pub->keydata.pkey != NULL);
188 REQUIRE(priv->keydata.pkey != NULL);
189 REQUIRE(priv->keydata.pkey->repr != NULL);
190 attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME);
191 if (attr == NULL)
192 return (DST_R_INVALIDPUBLICKEY);
193 REQUIRE(attr != NULL);
194 secLen = attr->ulValueLen;
195 attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
196 if (attr == NULL)
197 return (DST_R_INVALIDPUBLICKEY);
198
199 ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE, ISC_FALSE,
200 NULL, pk11_get_best_token(OP_DH));
201 if (ret != ISC_R_SUCCESS)
202 return (ret);
203
204 mech.ulParameterLen = attr->ulValueLen;
205 mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen);
206 if (mech.pParameter == NULL)
207 DST_RET(ISC_R_NOMEMORY);
208 memmove(mech.pParameter, attr->pValue, mech.ulParameterLen);
209
210 ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey);
211 if (ret != ISC_R_SUCCESS)
212 goto err;
213
214 PK11_RET(pkcs_C_DeriveKey,
215 (ctx.session, &mech, hKey,
216 keyTemplate, (CK_ULONG) 6, &hDerived),
217 DST_R_COMPUTESECRETFAILURE);
218
219 attr = valTemplate;
220 PK11_RET(pkcs_C_GetAttributeValue,
221 (ctx.session, hDerived, attr, (CK_ULONG) 1),
222 DST_R_CRYPTOFAILURE);
223 attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen);
224 if (attr->pValue == NULL)
225 DST_RET(ISC_R_NOMEMORY);
226 memset(attr->pValue, 0, attr->ulValueLen);
227 PK11_RET(pkcs_C_GetAttributeValue,
228 (ctx.session, hDerived, attr, (CK_ULONG) 1),
229 DST_R_CRYPTOFAILURE);
230
231 /* strip leading zeros */
232 secValue = (CK_BYTE_PTR) attr->pValue;
233 for (i = 0; i < attr->ulValueLen; i++)
234 if (secValue[i] != 0)
235 break;
236 isc_buffer_availableregion(secret, &r);
237 if (r.length < attr->ulValueLen - i)
238 DST_RET(ISC_R_NOSPACE);
239 memmove(r.base, secValue + i, attr->ulValueLen - i);
240 isc_buffer_add(secret, attr->ulValueLen - i);
241 ret = ISC_R_SUCCESS;
242
243 err:
244 if (hDerived != CK_INVALID_HANDLE)
245 (void) pkcs_C_DestroyObject(ctx.session, hDerived);
246 if (valTemplate[0].pValue != NULL) {
247 memset(valTemplate[0].pValue, 0, valTemplate[0].ulValueLen);
248 isc_mem_put(pub->mctx,
249 valTemplate[0].pValue,
250 valTemplate[0].ulValueLen);
251 }
252 if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken)
253 (void) pkcs_C_DestroyObject(ctx.session, hKey);
254 if (mech.pParameter != NULL) {
255 memset(mech.pParameter, 0, mech.ulParameterLen);
256 isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen);
257 }
258 pk11_return_session(&ctx);
259 return (ret);
260 }
261
262 static isc_boolean_t
pkcs11dh_compare(const dst_key_t * key1,const dst_key_t * key2)263 pkcs11dh_compare(const dst_key_t *key1, const dst_key_t *key2) {
264 pk11_object_t *dh1, *dh2;
265 CK_ATTRIBUTE *attr1, *attr2;
266
267 dh1 = key1->keydata.pkey;
268 dh2 = key2->keydata.pkey;
269
270 if ((dh1 == NULL) && (dh2 == NULL))
271 return (ISC_TRUE);
272 else if ((dh1 == NULL) || (dh2 == NULL))
273 return (ISC_FALSE);
274
275 attr1 = pk11_attribute_bytype(dh1, CKA_PRIME);
276 attr2 = pk11_attribute_bytype(dh2, CKA_PRIME);
277 if ((attr1 == NULL) && (attr2 == NULL))
278 return (ISC_TRUE);
279 else if ((attr1 == NULL) || (attr2 == NULL) ||
280 (attr1->ulValueLen != attr2->ulValueLen) ||
281 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
282 return (ISC_FALSE);
283
284 attr1 = pk11_attribute_bytype(dh1, CKA_BASE);
285 attr2 = pk11_attribute_bytype(dh2, CKA_BASE);
286 if ((attr1 == NULL) && (attr2 == NULL))
287 return (ISC_TRUE);
288 else if ((attr1 == NULL) || (attr2 == NULL) ||
289 (attr1->ulValueLen != attr2->ulValueLen) ||
290 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
291 return (ISC_FALSE);
292
293 attr1 = pk11_attribute_bytype(dh1, CKA_VALUE);
294 attr2 = pk11_attribute_bytype(dh2, CKA_VALUE);
295 if ((attr1 == NULL) && (attr2 == NULL))
296 return (ISC_TRUE);
297 else if ((attr1 == NULL) || (attr2 == NULL) ||
298 (attr1->ulValueLen != attr2->ulValueLen) ||
299 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
300 return (ISC_FALSE);
301
302 attr1 = pk11_attribute_bytype(dh1, CKA_VALUE2);
303 attr2 = pk11_attribute_bytype(dh2, CKA_VALUE2);
304 if (((attr1 != NULL) || (attr2 != NULL)) &&
305 ((attr1 == NULL) || (attr2 == NULL) ||
306 (attr1->ulValueLen != attr2->ulValueLen) ||
307 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
308 return (ISC_FALSE);
309
310 if (!dh1->ontoken && !dh2->ontoken)
311 return (ISC_TRUE);
312 else if (dh1->ontoken || dh2->ontoken ||
313 (dh1->object != dh2->object))
314 return (ISC_FALSE);
315
316 return (ISC_TRUE);
317 }
318
319 static isc_boolean_t
pkcs11dh_paramcompare(const dst_key_t * key1,const dst_key_t * key2)320 pkcs11dh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
321 pk11_object_t *dh1, *dh2;
322 CK_ATTRIBUTE *attr1, *attr2;
323
324 dh1 = key1->keydata.pkey;
325 dh2 = key2->keydata.pkey;
326
327 if ((dh1 == NULL) && (dh2 == NULL))
328 return (ISC_TRUE);
329 else if ((dh1 == NULL) || (dh2 == NULL))
330 return (ISC_FALSE);
331
332 attr1 = pk11_attribute_bytype(dh1, CKA_PRIME);
333 attr2 = pk11_attribute_bytype(dh2, CKA_PRIME);
334 if ((attr1 == NULL) && (attr2 == NULL))
335 return (ISC_TRUE);
336 else if ((attr1 == NULL) || (attr2 == NULL) ||
337 (attr1->ulValueLen != attr2->ulValueLen) ||
338 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
339 return (ISC_FALSE);
340
341 attr1 = pk11_attribute_bytype(dh1, CKA_BASE);
342 attr2 = pk11_attribute_bytype(dh2, CKA_BASE);
343 if ((attr1 == NULL) && (attr2 == NULL))
344 return (ISC_TRUE);
345 else if ((attr1 == NULL) || (attr2 == NULL) ||
346 (attr1->ulValueLen != attr2->ulValueLen) ||
347 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
348 return (ISC_FALSE);
349
350 return (ISC_TRUE);
351 }
352
353 static isc_result_t
pkcs11dh_generate(dst_key_t * key,int generator,void (* callback)(int))354 pkcs11dh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
355 CK_RV rv;
356 CK_MECHANISM mech = { CKM_DH_PKCS_PARAMETER_GEN, NULL, 0 };
357 CK_OBJECT_HANDLE domainparams = CK_INVALID_HANDLE;
358 CK_OBJECT_CLASS dClass = CKO_DOMAIN_PARAMETERS;
359 CK_KEY_TYPE keyType = CKK_DH;
360 CK_ULONG bits = 0;
361 CK_ATTRIBUTE dTemplate[] =
362 {
363 { CKA_CLASS, &dClass, (CK_ULONG) sizeof(dClass) },
364 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
365 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
366 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
367 { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) }
368 };
369 CK_ATTRIBUTE pTemplate[] =
370 {
371 { CKA_PRIME, NULL, 0 },
372 { CKA_BASE, NULL, 0 }
373 };
374 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
375 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
376 CK_ATTRIBUTE pubTemplate[] =
377 {
378 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
379 { CKA_KEY_TYPE,&keyType, (CK_ULONG) sizeof(keyType) },
380 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
381 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
382 { CKA_PRIME, NULL, 0 },
383 { CKA_BASE, NULL, 0 },
384 };
385 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
386 CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
387 CK_ATTRIBUTE privTemplate[] =
388 {
389 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
390 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
391 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
392 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
393 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
394 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
395 { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
396 };
397 CK_ATTRIBUTE *attr;
398 pk11_object_t *dh = NULL;
399 pk11_context_t *pk11_ctx;
400 isc_result_t ret;
401
402 UNUSED(callback);
403
404 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
405 sizeof(*pk11_ctx));
406 if (pk11_ctx == NULL)
407 return (ISC_R_NOMEMORY);
408 ret = pk11_get_session(pk11_ctx, OP_DH, ISC_TRUE, ISC_FALSE,
409 ISC_FALSE, NULL, pk11_get_best_token(OP_DH));
410 if (ret != ISC_R_SUCCESS)
411 goto err;
412
413 bits = key->key_size;
414 if ((generator == 0) &&
415 ((bits == 768) || (bits == 1024) || (bits == 1536))) {
416 if (bits == 768) {
417 pubTemplate[4].pValue =
418 isc_mem_get(key->mctx, sizeof(pk11_dh_bn768));
419 if (pubTemplate[4].pValue == NULL)
420 DST_RET(ISC_R_NOMEMORY);
421 memmove(pubTemplate[4].pValue,
422 pk11_dh_bn768, sizeof(pk11_dh_bn768));
423 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn768);
424 } else if (bits == 1024) {
425 pubTemplate[4].pValue =
426 isc_mem_get(key->mctx, sizeof(pk11_dh_bn1024));
427 if (pubTemplate[4].pValue == NULL)
428 DST_RET(ISC_R_NOMEMORY);
429 memmove(pubTemplate[4].pValue,
430 pk11_dh_bn1024, sizeof(pk11_dh_bn1024));
431 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1024);
432 } else {
433 pubTemplate[4].pValue =
434 isc_mem_get(key->mctx, sizeof(pk11_dh_bn1536));
435 if (pubTemplate[4].pValue == NULL)
436 DST_RET(ISC_R_NOMEMORY);
437 memmove(pubTemplate[4].pValue,
438 pk11_dh_bn1536, sizeof(pk11_dh_bn1536));
439 pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1536);
440 }
441 pubTemplate[5].pValue = isc_mem_get(key->mctx,
442 sizeof(pk11_dh_bn2));
443 if (pubTemplate[5].pValue == NULL)
444 DST_RET(ISC_R_NOMEMORY);
445 memmove(pubTemplate[5].pValue, pk11_dh_bn2,
446 sizeof(pk11_dh_bn2));
447 pubTemplate[5].ulValueLen = sizeof(pk11_dh_bn2);
448 } else {
449 PK11_RET(pkcs_C_GenerateKey,
450 (pk11_ctx->session, &mech,
451 dTemplate, (CK_ULONG) 5, &domainparams),
452 DST_R_CRYPTOFAILURE);
453 PK11_RET(pkcs_C_GetAttributeValue,
454 (pk11_ctx->session, domainparams,
455 pTemplate, (CK_ULONG) 2),
456 DST_R_CRYPTOFAILURE);
457 pTemplate[0].pValue = isc_mem_get(key->mctx,
458 pTemplate[0].ulValueLen);
459 if (pTemplate[0].pValue == NULL)
460 DST_RET(ISC_R_NOMEMORY);
461 memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen);
462 pTemplate[1].pValue = isc_mem_get(key->mctx,
463 pTemplate[1].ulValueLen);
464 if (pTemplate[1].pValue == NULL)
465 DST_RET(ISC_R_NOMEMORY);
466 memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen);
467 PK11_RET(pkcs_C_GetAttributeValue,
468 (pk11_ctx->session, domainparams,
469 pTemplate, (CK_ULONG) 2),
470 DST_R_CRYPTOFAILURE);
471
472 pubTemplate[4].pValue = pTemplate[0].pValue;
473 pubTemplate[4].ulValueLen = pTemplate[0].ulValueLen;
474 pTemplate[0].pValue = NULL;
475 pubTemplate[5].pValue = pTemplate[1].pValue;
476 pubTemplate[5].ulValueLen = pTemplate[1].ulValueLen;
477 pTemplate[1].pValue = NULL;
478 }
479
480 mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
481 PK11_RET(pkcs_C_GenerateKeyPair,
482 (pk11_ctx->session, &mech,
483 pubTemplate, (CK_ULONG) 6,
484 privTemplate, (CK_ULONG) 7,
485 &pub, &priv),
486 DST_R_CRYPTOFAILURE);
487
488 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
489 if (dh == NULL)
490 DST_RET(ISC_R_NOMEMORY);
491 memset(dh, 0, sizeof(*dh));
492 key->keydata.pkey = dh;
493 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
494 if (dh->repr == NULL)
495 DST_RET(ISC_R_NOMEMORY);
496 memset(dh->repr, 0, sizeof(*attr) * 4);
497 dh->attrcnt = 4;
498
499 attr = dh->repr;
500 attr[0].type = CKA_PRIME;
501 attr[0].pValue = pubTemplate[4].pValue;
502 attr[0].ulValueLen = pubTemplate[4].ulValueLen;
503 pubTemplate[4].pValue = NULL;
504
505 attr[1].type = CKA_BASE;
506 attr[1].pValue = pubTemplate[5].pValue;
507 attr[1].ulValueLen = pubTemplate[5].ulValueLen;
508 pubTemplate[5].pValue =NULL;
509
510 attr += 2;
511 attr->type = CKA_VALUE;
512 PK11_RET(pkcs_C_GetAttributeValue,
513 (pk11_ctx->session, pub, attr, 1),
514 DST_R_CRYPTOFAILURE);
515 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
516 if (attr->pValue == NULL)
517 DST_RET(ISC_R_NOMEMORY);
518 memset(attr->pValue, 0, attr->ulValueLen);
519 PK11_RET(pkcs_C_GetAttributeValue,
520 (pk11_ctx->session, pub, attr, 1),
521 DST_R_CRYPTOFAILURE);
522
523 attr++;
524 attr->type = CKA_VALUE;
525 PK11_RET(pkcs_C_GetAttributeValue,
526 (pk11_ctx->session, priv, attr, 1),
527 DST_R_CRYPTOFAILURE);
528 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
529 if (attr->pValue == NULL)
530 DST_RET(ISC_R_NOMEMORY);
531 memset(attr->pValue, 0, attr->ulValueLen);
532 PK11_RET(pkcs_C_GetAttributeValue,
533 (pk11_ctx->session, priv, attr, 1),
534 DST_R_CRYPTOFAILURE);
535 attr->type = CKA_VALUE2;
536
537 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
538 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
539 (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
540 pk11_return_session(pk11_ctx);
541 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
542 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
543
544 return (ISC_R_SUCCESS);
545
546 err:
547 pkcs11dh_destroy(key);
548 if (priv != CK_INVALID_HANDLE)
549 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
550 if (pub != CK_INVALID_HANDLE)
551 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
552 if (domainparams != CK_INVALID_HANDLE)
553 (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
554
555 if (pubTemplate[4].pValue != NULL) {
556 memset(pubTemplate[4].pValue, 0, pubTemplate[4].ulValueLen);
557 isc_mem_put(key->mctx,
558 pubTemplate[4].pValue,
559 pubTemplate[4].ulValueLen);
560 }
561 if (pubTemplate[5].pValue != NULL) {
562 memset(pubTemplate[5].pValue, 0, pubTemplate[5].ulValueLen);
563 isc_mem_put(key->mctx,
564 pubTemplate[5].pValue,
565 pubTemplate[5].ulValueLen);
566 }
567 if (pTemplate[0].pValue != NULL) {
568 memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen);
569 isc_mem_put(key->mctx,
570 pTemplate[0].pValue,
571 pTemplate[0].ulValueLen);
572 }
573 if (pTemplate[1].pValue != NULL) {
574 memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen);
575 isc_mem_put(key->mctx,
576 pTemplate[1].pValue,
577 pTemplate[1].ulValueLen);
578 }
579
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));
583
584 return (ret);
585 }
586
587 static isc_boolean_t
pkcs11dh_isprivate(const dst_key_t * key)588 pkcs11dh_isprivate(const dst_key_t *key) {
589 pk11_object_t *dh = key->keydata.pkey;
590 CK_ATTRIBUTE *attr;
591
592 if (dh == NULL)
593 return (ISC_FALSE);
594 attr = pk11_attribute_bytype(dh, CKA_VALUE2);
595 return (ISC_TF((attr != NULL) || dh->ontoken));
596 }
597
598 static void
pkcs11dh_destroy(dst_key_t * key)599 pkcs11dh_destroy(dst_key_t *key) {
600 pk11_object_t *dh = key->keydata.pkey;
601 CK_ATTRIBUTE *attr;
602
603 if (dh == NULL)
604 return;
605
606 INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken);
607
608 for (attr = pk11_attribute_first(dh);
609 attr != NULL;
610 attr = pk11_attribute_next(dh, attr))
611 switch (attr->type) {
612 case CKA_VALUE:
613 case CKA_VALUE2:
614 case CKA_PRIME:
615 case CKA_BASE:
616 if (attr->pValue != NULL) {
617 memset(attr->pValue, 0, attr->ulValueLen);
618 isc_mem_put(key->mctx,
619 attr->pValue,
620 attr->ulValueLen);
621 }
622 break;
623 }
624 if (dh->repr != NULL) {
625 memset(dh->repr, 0, dh->attrcnt * sizeof(*attr));
626 isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
627 }
628 memset(dh, 0, sizeof(*dh));
629 isc_mem_put(key->mctx, dh, sizeof(*dh));
630 key->keydata.pkey = NULL;
631 }
632
633 static void
uint16_toregion(isc_uint16_t val,isc_region_t * region)634 uint16_toregion(isc_uint16_t val, isc_region_t *region) {
635 *region->base = (val & 0xff00) >> 8;
636 isc_region_consume(region, 1);
637 *region->base = (val & 0x00ff);
638 isc_region_consume(region, 1);
639 }
640
641 static isc_uint16_t
uint16_fromregion(isc_region_t * region)642 uint16_fromregion(isc_region_t *region) {
643 isc_uint16_t val;
644 unsigned char *cp = region->base;
645
646 val = ((unsigned int)(cp[0])) << 8;
647 val |= ((unsigned int)(cp[1]));
648
649 isc_region_consume(region, 2);
650
651 return (val);
652 }
653
654 static isc_result_t
pkcs11dh_todns(const dst_key_t * key,isc_buffer_t * data)655 pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) {
656 pk11_object_t *dh;
657 CK_ATTRIBUTE *attr;
658 isc_region_t r;
659 isc_uint16_t dnslen, plen = 0, glen = 0, publen = 0;
660 CK_BYTE *prime = NULL, *base = NULL, *pub = NULL;
661
662 REQUIRE(key->keydata.pkey != NULL);
663
664 dh = key->keydata.pkey;
665
666 for (attr = pk11_attribute_first(dh);
667 attr != NULL;
668 attr = pk11_attribute_next(dh, attr))
669 switch (attr->type) {
670 case CKA_VALUE:
671 pub = (CK_BYTE *) attr->pValue;
672 publen = (isc_uint16_t) attr->ulValueLen;
673 break;
674 case CKA_PRIME:
675 prime = (CK_BYTE *) attr->pValue;
676 plen = (isc_uint16_t) attr->ulValueLen;
677 break;
678 case CKA_BASE:
679 base = (CK_BYTE *) attr->pValue;
680 glen = (isc_uint16_t) attr->ulValueLen;
681 break;
682 }
683 REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL));
684
685 isc_buffer_availableregion(data, &r);
686
687 if ((glen == 1) && (memcmp(pk11_dh_bn2, base, glen) == 0) &&
688 (((plen == sizeof(pk11_dh_bn768)) &&
689 (memcmp(pk11_dh_bn768, prime, plen) == 0)) ||
690 ((plen == sizeof(pk11_dh_bn1024)) &&
691 (memcmp(pk11_dh_bn1024, prime, plen) == 0)) ||
692 ((plen == sizeof(pk11_dh_bn1536)) &&
693 (memcmp(pk11_dh_bn1536, prime, plen) == 0)))) {
694 plen = 1;
695 glen = 0;
696 }
697
698 dnslen = plen + glen + publen + 6;
699 if (r.length < (unsigned int) dnslen)
700 return (ISC_R_NOSPACE);
701
702 uint16_toregion(plen, &r);
703 if (plen == 1) {
704 if (memcmp(pk11_dh_bn768, prime, sizeof(pk11_dh_bn768)) == 0)
705 *r.base = 1;
706 else if (memcmp(pk11_dh_bn1024, prime,
707 sizeof(pk11_dh_bn1024)) == 0)
708 *r.base = 2;
709 else
710 *r.base = 3;
711 }
712 else
713 memmove(r.base, prime, plen);
714 isc_region_consume(&r, plen);
715
716 uint16_toregion(glen, &r);
717 if (glen > 0)
718 memmove(r.base, base, glen);
719 isc_region_consume(&r, glen);
720
721 uint16_toregion(publen, &r);
722 memmove(r.base, pub, publen);
723 isc_region_consume(&r, publen);
724
725 isc_buffer_add(data, dnslen);
726
727 return (ISC_R_SUCCESS);
728 }
729
730 static isc_result_t
pkcs11dh_fromdns(dst_key_t * key,isc_buffer_t * data)731 pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) {
732 pk11_object_t *dh;
733 isc_region_t r;
734 isc_uint16_t plen, glen, plen_, glen_, publen;
735 CK_BYTE *prime = NULL, *base = NULL, *pub = NULL;
736 CK_ATTRIBUTE *attr;
737 int special = 0;
738
739 isc_buffer_remainingregion(data, &r);
740 if (r.length == 0)
741 return (ISC_R_SUCCESS);
742
743 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
744 if (dh == NULL)
745 return (ISC_R_NOMEMORY);
746 memset(dh, 0, sizeof(*dh));
747
748 /*
749 * Read the prime length. 1 & 2 are table entries, > 16 means a
750 * prime follows, otherwise an error.
751 */
752 if (r.length < 2) {
753 memset(dh, 0, sizeof(*dh));
754 isc_mem_put(key->mctx, dh, sizeof(*dh));
755 return (DST_R_INVALIDPUBLICKEY);
756 }
757 plen = uint16_fromregion(&r);
758 if (plen < 16 && plen != 1 && plen != 2) {
759 memset(dh, 0, sizeof(*dh));
760 isc_mem_put(key->mctx, dh, sizeof(*dh));
761 return (DST_R_INVALIDPUBLICKEY);
762 }
763 if (r.length < plen) {
764 memset(dh, 0, sizeof(*dh));
765 isc_mem_put(key->mctx, dh, sizeof(*dh));
766 return (DST_R_INVALIDPUBLICKEY);
767 }
768 plen_ = plen;
769 if (plen == 1 || plen == 2) {
770 if (plen == 1) {
771 special = *r.base;
772 isc_region_consume(&r, 1);
773 } else {
774 special = uint16_fromregion(&r);
775 }
776 switch (special) {
777 case 1:
778 prime = pk11_dh_bn768;
779 plen_ = sizeof(pk11_dh_bn768);
780 break;
781 case 2:
782 prime = pk11_dh_bn1024;
783 plen_ = sizeof(pk11_dh_bn1024);
784 break;
785 case 3:
786 prime = pk11_dh_bn1536;
787 plen_ = sizeof(pk11_dh_bn1536);
788 break;
789 default:
790 memset(dh, 0, sizeof(*dh));
791 isc_mem_put(key->mctx, dh, sizeof(*dh));
792 return (DST_R_INVALIDPUBLICKEY);
793 }
794 }
795 else {
796 prime = r.base;
797 isc_region_consume(&r, plen);
798 }
799
800 /*
801 * Read the generator length. This should be 0 if the prime was
802 * special, but it might not be. If it's 0 and the prime is not
803 * special, we have a problem.
804 */
805 if (r.length < 2) {
806 memset(dh, 0, sizeof(*dh));
807 isc_mem_put(key->mctx, dh, sizeof(*dh));
808 return (DST_R_INVALIDPUBLICKEY);
809 }
810 glen = uint16_fromregion(&r);
811 if (r.length < glen) {
812 memset(dh, 0, sizeof(*dh));
813 isc_mem_put(key->mctx, dh, sizeof(*dh));
814 return (DST_R_INVALIDPUBLICKEY);
815 }
816 glen_ = glen;
817 if (special != 0) {
818 if (glen == 0) {
819 base = pk11_dh_bn2;
820 glen_ = sizeof(pk11_dh_bn2);
821 }
822 else {
823 base = r.base;
824 if (memcmp(base, pk11_dh_bn2, glen) == 0) {
825 base = pk11_dh_bn2;
826 glen_ = sizeof(pk11_dh_bn2);
827 }
828 else {
829 memset(dh, 0, sizeof(*dh));
830 isc_mem_put(key->mctx, dh, sizeof(*dh));
831 return (DST_R_INVALIDPUBLICKEY);
832 }
833 }
834 }
835 else {
836 if (glen == 0) {
837 memset(dh, 0, sizeof(*dh));
838 isc_mem_put(key->mctx, dh, sizeof(*dh));
839 return (DST_R_INVALIDPUBLICKEY);
840 }
841 base = r.base;
842 }
843 isc_region_consume(&r, glen);
844
845 if (r.length < 2) {
846 memset(dh, 0, sizeof(*dh));
847 isc_mem_put(key->mctx, dh, sizeof(*dh));
848 return (DST_R_INVALIDPUBLICKEY);
849 }
850 publen = uint16_fromregion(&r);
851 if (r.length < publen) {
852 memset(dh, 0, sizeof(*dh));
853 isc_mem_put(key->mctx, dh, sizeof(*dh));
854 return (DST_R_INVALIDPUBLICKEY);
855 }
856 pub = r.base;
857 isc_region_consume(&r, publen);
858
859 key->key_size = pk11_numbits(prime, plen_);
860
861 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
862 if (dh->repr == NULL)
863 goto nomemory;
864 memset(dh->repr, 0, sizeof(*attr) * 3);
865 dh->attrcnt = 3;
866
867 attr = dh->repr;
868 attr[0].type = CKA_PRIME;
869 attr[0].pValue = isc_mem_get(key->mctx, plen_);
870 if (attr[0].pValue == NULL)
871 goto nomemory;
872 memmove(attr[0].pValue, prime, plen_);
873 attr[0].ulValueLen = (CK_ULONG) plen_;
874
875 attr[1].type = CKA_BASE;
876 attr[1].pValue = isc_mem_get(key->mctx, glen_);
877 if (attr[1].pValue == NULL)
878 goto nomemory;
879 memmove(attr[1].pValue, base, glen_);
880 attr[1].ulValueLen = (CK_ULONG) glen_;
881
882 attr[2].type = CKA_VALUE;
883 attr[2].pValue = isc_mem_get(key->mctx, publen);
884 if (attr[2].pValue == NULL)
885 goto nomemory;
886 memmove(attr[2].pValue, pub, publen);
887 attr[2].ulValueLen = (CK_ULONG) publen;
888
889 isc_buffer_forward(data, plen + glen + publen + 6);
890
891 key->keydata.pkey = dh;
892
893 return (ISC_R_SUCCESS);
894
895 nomemory:
896 for (attr = pk11_attribute_first(dh);
897 attr != NULL;
898 attr = pk11_attribute_next(dh, attr))
899 switch (attr->type) {
900 case CKA_VALUE:
901 case CKA_PRIME:
902 case CKA_BASE:
903 if (attr->pValue != NULL) {
904 memset(attr->pValue, 0, attr->ulValueLen);
905 isc_mem_put(key->mctx,
906 attr->pValue,
907 attr->ulValueLen);
908 }
909 break;
910 }
911 if (dh->repr != NULL) {
912 memset(dh->repr, 0, dh->attrcnt * sizeof(*attr));
913 isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
914 }
915 memset(dh, 0, sizeof(*dh));
916 isc_mem_put(key->mctx, dh, sizeof(*dh));
917 return (ISC_R_NOMEMORY);
918 }
919
920 static isc_result_t
pkcs11dh_tofile(const dst_key_t * key,const char * directory)921 pkcs11dh_tofile(const dst_key_t *key, const char *directory) {
922 int i;
923 pk11_object_t *dh;
924 CK_ATTRIBUTE *attr;
925 CK_ATTRIBUTE *prime = NULL, *base = NULL, *pub = NULL, *prv = NULL;
926 dst_private_t priv;
927 unsigned char *bufs[4];
928 isc_result_t result;
929
930 if (key->keydata.pkey == NULL)
931 return (DST_R_NULLKEY);
932
933 if (key->external)
934 return (DST_R_EXTERNALKEY);
935
936 dh = key->keydata.pkey;
937
938 for (attr = pk11_attribute_first(dh);
939 attr != NULL;
940 attr = pk11_attribute_next(dh, attr))
941 switch (attr->type) {
942 case CKA_VALUE:
943 pub = attr;
944 break;
945 case CKA_VALUE2:
946 prv = attr;
947 break;
948 case CKA_PRIME:
949 prime = attr;
950 break;
951 case CKA_BASE:
952 base = attr;
953 break;
954 }
955 if ((prime == NULL) || (base == NULL) ||
956 (pub == NULL) || (prv == NULL))
957 return (DST_R_NULLKEY);
958
959 memset(bufs, 0, sizeof(bufs));
960 for (i = 0; i < 4; i++) {
961 bufs[i] = isc_mem_get(key->mctx, prime->ulValueLen);
962 if (bufs[i] == NULL) {
963 result = ISC_R_NOMEMORY;
964 goto fail;
965 }
966 memset(bufs[i], 0, prime->ulValueLen);
967 }
968
969 i = 0;
970
971 priv.elements[i].tag = TAG_DH_PRIME;
972 priv.elements[i].length = (unsigned short) prime->ulValueLen;
973 memmove(bufs[i], prime->pValue, prime->ulValueLen);
974 priv.elements[i].data = bufs[i];
975 i++;
976
977 priv.elements[i].tag = TAG_DH_GENERATOR;
978 priv.elements[i].length = (unsigned short) base->ulValueLen;
979 memmove(bufs[i], base->pValue, base->ulValueLen);
980 priv.elements[i].data = bufs[i];
981 i++;
982
983 priv.elements[i].tag = TAG_DH_PRIVATE;
984 priv.elements[i].length = (unsigned short) prv->ulValueLen;
985 memmove(bufs[i], prv->pValue, prv->ulValueLen);
986 priv.elements[i].data = bufs[i];
987 i++;
988
989 priv.elements[i].tag = TAG_DH_PUBLIC;
990 priv.elements[i].length = (unsigned short) pub->ulValueLen;
991 memmove(bufs[i], pub->pValue, pub->ulValueLen);
992 priv.elements[i].data = bufs[i];
993 i++;
994
995 priv.nelements = i;
996 result = dst__privstruct_writefile(key, &priv, directory);
997 fail:
998 for (i = 0; i < 4; i++) {
999 if (bufs[i] == NULL)
1000 break;
1001 memset(bufs[i], 0, prime->ulValueLen);
1002 isc_mem_put(key->mctx, bufs[i], prime->ulValueLen);
1003 }
1004 return (result);
1005 }
1006
1007 static isc_result_t
pkcs11dh_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)1008 pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1009 dst_private_t priv;
1010 isc_result_t ret;
1011 int i;
1012 pk11_object_t *dh = NULL;
1013 CK_ATTRIBUTE *attr;
1014 isc_mem_t *mctx;
1015
1016 UNUSED(pub);
1017 mctx = key->mctx;
1018
1019 /* read private key file */
1020 ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
1021 if (ret != ISC_R_SUCCESS)
1022 return (ret);
1023
1024 if (key->external)
1025 DST_RET(DST_R_EXTERNALKEY);
1026
1027 dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
1028 if (dh == NULL)
1029 DST_RET(ISC_R_NOMEMORY);
1030 memset(dh, 0, sizeof(*dh));
1031 key->keydata.pkey = dh;
1032 dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
1033 if (dh->repr == NULL)
1034 DST_RET(ISC_R_NOMEMORY);
1035 memset(dh->repr, 0, sizeof(*attr) * 4);
1036 dh->attrcnt = 4;
1037 attr = dh->repr;
1038 attr[0].type = CKA_PRIME;
1039 attr[1].type = CKA_BASE;
1040 attr[2].type = CKA_VALUE;
1041 attr[3].type = CKA_VALUE2;
1042
1043 for (i = 0; i < priv.nelements; i++) {
1044 CK_BYTE *bn;
1045
1046 bn = isc_mem_get(key->mctx, priv.elements[i].length);
1047 if (bn == NULL)
1048 DST_RET(ISC_R_NOMEMORY);
1049 memmove(bn, priv.elements[i].data, priv.elements[i].length);
1050
1051 switch (priv.elements[i].tag) {
1052 case TAG_DH_PRIME:
1053 attr = pk11_attribute_bytype(dh, CKA_PRIME);
1054 INSIST(attr != NULL);
1055 attr->pValue = bn;
1056 attr->ulValueLen = priv.elements[i].length;
1057 break;
1058 case TAG_DH_GENERATOR:
1059 attr = pk11_attribute_bytype(dh, CKA_BASE);
1060 INSIST(attr != NULL);
1061 attr->pValue = bn;
1062 attr->ulValueLen = priv.elements[i].length;
1063 break;
1064 case TAG_DH_PRIVATE:
1065 attr = pk11_attribute_bytype(dh, CKA_VALUE2);
1066 INSIST(attr != NULL);
1067 attr->pValue = bn;
1068 attr->ulValueLen = priv.elements[i].length;
1069 break;
1070 case TAG_DH_PUBLIC:
1071 attr = pk11_attribute_bytype(dh, CKA_VALUE);
1072 INSIST(attr != NULL);
1073 attr->pValue = bn;
1074 attr->ulValueLen = priv.elements[i].length;
1075 break;
1076 }
1077 }
1078 dst__privstruct_free(&priv, mctx);
1079
1080 attr = pk11_attribute_bytype(dh, CKA_PRIME);
1081 INSIST(attr != NULL);
1082 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
1083
1084 return (ISC_R_SUCCESS);
1085
1086 err:
1087 pkcs11dh_destroy(key);
1088 dst__privstruct_free(&priv, mctx);
1089 memset(&priv, 0, sizeof(priv));
1090 return (ret);
1091 }
1092
1093 static dst_func_t pkcs11dh_functions = {
1094 NULL, /*%< createctx */
1095 NULL, /*%< createctx2 */
1096 NULL, /*%< destroyctx */
1097 NULL, /*%< adddata */
1098 NULL, /*%< sign */
1099 NULL, /*%< verify */
1100 NULL, /*%< verify2 */
1101 pkcs11dh_computesecret,
1102 pkcs11dh_compare,
1103 pkcs11dh_paramcompare,
1104 pkcs11dh_generate,
1105 pkcs11dh_isprivate,
1106 pkcs11dh_destroy,
1107 pkcs11dh_todns,
1108 pkcs11dh_fromdns,
1109 pkcs11dh_tofile,
1110 pkcs11dh_parse,
1111 NULL, /*%< cleanup */
1112 NULL, /*%< fromlabel */
1113 NULL, /*%< dump */
1114 NULL, /*%< restore */
1115 };
1116
1117 isc_result_t
dst__pkcs11dh_init(dst_func_t ** funcp)1118 dst__pkcs11dh_init(dst_func_t **funcp) {
1119 REQUIRE(funcp != NULL);
1120 if (*funcp == NULL)
1121 *funcp = &pkcs11dh_functions;
1122 return (ISC_R_SUCCESS);
1123 }
1124
1125 #else /* PKCS11CRYPTO */
1126
1127 #include <isc/util.h>
1128
1129 EMPTY_TRANSLATION_UNIT
1130
1131 #endif /* PKCS11CRYPTO */
1132 /*! \file */
1133