Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / pkcs11dh_link.c
blob740d44f26d162b4d794da3aa2be05af374e0951d
1 /* $NetBSD: pkcs11dh_link.c,v 1.1.1.5 2015/09/03 07:21:36 christos Exp $ */
3 /*
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.
19 #ifdef PKCS11CRYPTO
21 #include <config.h>
23 #include <ctype.h>
25 #include <isc/mem.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
29 #include <dst/result.h>
31 #include "dst_internal.h"
32 #include "dst_parse.h"
33 #include "dst_pkcs11.h"
35 #include <pk11/pk11.h>
36 #include <pk11/internal.h>
37 #define WANT_DH_PRIMES
38 #include <pk11/constants.h>
40 #include <pkcs11/pkcs11.h>
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
70 #define CKA_VALUE2 CKA_PRIVATE_EXPONENT
72 static CK_BBOOL truevalue = TRUE;
73 static CK_BBOOL falsevalue = FALSE;
75 #define DST_RET(a) {ret = a; goto err;}
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);
80 static isc_result_t
81 pkcs11dh_loadpriv(const dst_key_t *key,
82 CK_SESSION_HANDLE session,
83 CK_OBJECT_HANDLE *hKey)
85 CK_RV rv;
86 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
87 CK_KEY_TYPE keyType = CKK_DH;
88 CK_ATTRIBUTE keyTemplate[] =
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 }
100 CK_ATTRIBUTE *attr;
101 const pk11_object_t *priv;
102 isc_result_t ret;
103 unsigned int i;
105 priv = key->keydata.pkey;
106 if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
107 *hKey = priv->object;
108 return (ISC_R_SUCCESS);
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;
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;
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;
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;
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);
153 return (ret);
156 static isc_result_t
157 pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
158 isc_buffer_t *secret)
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[] =
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) }
177 CK_ATTRIBUTE valTemplate[] =
179 { CKA_VALUE, NULL, 0 }
181 CK_BYTE *secValue;
182 pk11_context_t ctx;
183 isc_result_t ret;
184 unsigned int i;
185 isc_region_t r;
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);
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);
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);
210 ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey);
211 if (ret != ISC_R_SUCCESS)
212 goto err;
214 PK11_RET(pkcs_C_DeriveKey,
215 (ctx.session, &mech, hKey,
216 keyTemplate, (CK_ULONG) 6, &hDerived),
217 DST_R_COMPUTESECRETFAILURE);
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);
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;
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);
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);
258 pk11_return_session(&ctx);
259 return (ret);
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;
267 dh1 = key1->keydata.pkey;
268 dh2 = key2->keydata.pkey;
270 if ((dh1 == NULL) && (dh2 == NULL))
271 return (ISC_TRUE);
272 else if ((dh1 == NULL) || (dh2 == NULL))
273 return (ISC_FALSE);
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);
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);
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);
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);
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);
316 return (ISC_TRUE);
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;
324 dh1 = key1->keydata.pkey;
325 dh2 = key2->keydata.pkey;
327 if ((dh1 == NULL) && (dh2 == NULL))
328 return (ISC_TRUE);
329 else if ((dh1 == NULL) || (dh2 == NULL))
330 return (ISC_FALSE);
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);
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);
350 return (ISC_TRUE);
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[] =
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) }
369 CK_ATTRIBUTE pTemplate[] =
371 { CKA_PRIME, NULL, 0 },
372 { CKA_BASE, NULL, 0 }
374 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
375 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
376 CK_ATTRIBUTE pubTemplate[] =
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 },
385 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
386 CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
387 CK_ATTRIBUTE privTemplate[] =
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) },
397 CK_ATTRIBUTE *attr;
398 pk11_object_t *dh = NULL;
399 pk11_context_t *pk11_ctx;
400 isc_result_t ret;
402 UNUSED(callback);
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;
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);
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);
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;
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);
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;
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;
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;
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);
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;
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));
544 return (ISC_R_SUCCESS);
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);
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);
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);
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);
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);
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));
584 return (ret);
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;
592 if (dh == NULL)
593 return (ISC_FALSE);
594 attr = pk11_attribute_bytype(dh, CKA_VALUE2);
595 return (ISC_TF((attr != NULL) || dh->ontoken));
598 static void
599 pkcs11dh_destroy(dst_key_t *key) {
600 pk11_object_t *dh = key->keydata.pkey;
601 CK_ATTRIBUTE *attr;
603 if (dh == NULL)
604 return;
606 INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken);
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);
622 break;
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));
628 memset(dh, 0, sizeof(*dh));
629 isc_mem_put(key->mctx, dh, sizeof(*dh));
630 key->keydata.pkey = NULL;
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);
641 static isc_uint16_t
642 uint16_fromregion(isc_region_t *region) {
643 isc_uint16_t val;
644 unsigned char *cp = region->base;
646 val = ((unsigned int)(cp[0])) << 8;
647 val |= ((unsigned int)(cp[1]));
649 isc_region_consume(region, 2);
651 return (val);
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;
662 REQUIRE(key->keydata.pkey != NULL);
664 dh = key->keydata.pkey;
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;
683 REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL));
685 isc_buffer_availableregion(data, &r);
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;
698 dnslen = plen + glen + publen + 6;
699 if (r.length < (unsigned int) dnslen)
700 return (ISC_R_NOSPACE);
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;
712 else
713 memmove(r.base, prime, plen);
714 isc_region_consume(&r, plen);
716 uint16_toregion(glen, &r);
717 if (glen > 0)
718 memmove(r.base, base, glen);
719 isc_region_consume(&r, glen);
721 uint16_toregion(publen, &r);
722 memmove(r.base, pub, publen);
723 isc_region_consume(&r, publen);
725 isc_buffer_add(data, dnslen);
727 return (ISC_R_SUCCESS);
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;
739 isc_buffer_remainingregion(data, &r);
740 if (r.length == 0)
741 return (ISC_R_SUCCESS);
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));
749 * Read the prime length. 1 & 2 are table entries, > 16 means a
750 * prime follows, otherwise an error.
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);
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);
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);
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);
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);
795 else {
796 prime = r.base;
797 isc_region_consume(&r, plen);
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.
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);
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);
816 glen_ = glen;
817 if (special != 0) {
818 if (glen == 0) {
819 base = pk11_dh_bn2;
820 glen_ = sizeof(pk11_dh_bn2);
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);
828 else {
829 memset(dh, 0, sizeof(*dh));
830 isc_mem_put(key->mctx, dh, sizeof(*dh));
831 return (DST_R_INVALIDPUBLICKEY);
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);
841 base = r.base;
843 isc_region_consume(&r, glen);
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);
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);
856 pub = r.base;
857 isc_region_consume(&r, publen);
859 key->key_size = pk11_numbits(prime, plen_);
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;
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_;
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_;
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;
889 isc_buffer_forward(data, plen + glen + publen + 6);
891 key->keydata.pkey = dh;
893 return (ISC_R_SUCCESS);
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);
909 break;
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));
915 memset(dh, 0, sizeof(*dh));
916 isc_mem_put(key->mctx, dh, sizeof(*dh));
917 return (ISC_R_NOMEMORY);
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;
930 if (key->keydata.pkey == NULL)
931 return (DST_R_NULLKEY);
933 if (key->external)
934 return (DST_R_EXTERNALKEY);
936 dh = key->keydata.pkey;
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;
955 if ((prime == NULL) || (base == NULL) ||
956 (pub == NULL) || (prv == NULL))
957 return (DST_R_NULLKEY);
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;
966 memset(bufs[i], 0, prime->ulValueLen);
969 i = 0;
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++;
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++;
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++;
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++;
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);
1004 return (result);
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;
1016 UNUSED(pub);
1017 mctx = key->mctx;
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);
1024 if (key->external)
1025 DST_RET(DST_R_EXTERNALKEY);
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;
1043 for (i = 0; i < priv.nelements; i++) {
1044 CK_BYTE *bn;
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);
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;
1078 dst__privstruct_free(&priv, mctx);
1080 attr = pk11_attribute_bytype(dh, CKA_PRIME);
1081 INSIST(attr != NULL);
1082 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
1084 return (ISC_R_SUCCESS);
1086 err:
1087 pkcs11dh_destroy(key);
1088 dst__privstruct_free(&priv, mctx);
1089 memset(&priv, 0, sizeof(priv));
1090 return (ret);
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 */
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);
1125 #else /* PKCS11CRYPTO */
1127 #include <isc/util.h>
1129 EMPTY_TRANSLATION_UNIT
1131 #endif /* PKCS11CRYPTO */
1132 /*! \file */