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
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
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
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
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
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
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
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
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
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
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
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
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
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
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