1 /* $NetBSD: pkcs11dh_link.c,v 1.1.1.5 2015/09/03 07:21:36 christos Exp $ */
4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
26 #include <isc/string.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>
45 * CKM_DH_PKCS_PARAMETER_GEN,
46 * CKM_DH_PKCS_KEY_PAIR_GEN,
49 * object class CKO_DOMAIN_PARAMETERS
51 * attribute CKA_PRIME (prime p)
52 * attribute CKA_BASE (base g)
53 * optional attribute CKA_PRIME_BITS (p length in bits)
55 * object class CKO_PUBLIC_KEY
57 * attribute CKA_PRIME (prime p)
58 * attribute CKA_BASE (base g)
59 * attribute CKA_VALUE (public value y)
61 * object class CKO_PRIVATE_KEY
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
);
81 pkcs11dh_loadpriv(const dst_key_t
*key
,
82 CK_SESSION_HANDLE session
,
83 CK_OBJECT_HANDLE
*hKey
)
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 }
101 const pk11_object_t
*priv
;
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
);
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
);
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
);
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
);
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
);
157 pkcs11dh_computesecret(const dst_key_t
*pub
, const dst_key_t
*priv
,
158 isc_buffer_t
*secret
)
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
;
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 }
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
);
192 return (DST_R_INVALIDPUBLICKEY
);
193 REQUIRE(attr
!= NULL
);
194 secLen
= attr
->ulValueLen
;
195 attr
= pk11_attribute_bytype(pub
->keydata
.pkey
, CKA_VALUE
);
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
)
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
)
214 PK11_RET(pkcs_C_DeriveKey
,
215 (ctx
.session
, &mech
, hKey
,
216 keyTemplate
, (CK_ULONG
) 6, &hDerived
),
217 DST_R_COMPUTESECRETFAILURE
);
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)
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
);
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
);
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
))
272 else if ((dh1
== NULL
) || (dh2
== NULL
))
275 attr1
= pk11_attribute_bytype(dh1
, CKA_PRIME
);
276 attr2
= pk11_attribute_bytype(dh2
, CKA_PRIME
);
277 if ((attr1
== NULL
) && (attr2
== NULL
))
279 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
280 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
281 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
284 attr1
= pk11_attribute_bytype(dh1
, CKA_BASE
);
285 attr2
= pk11_attribute_bytype(dh2
, CKA_BASE
);
286 if ((attr1
== NULL
) && (attr2
== NULL
))
288 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
289 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
290 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
293 attr1
= pk11_attribute_bytype(dh1
, CKA_VALUE
);
294 attr2
= pk11_attribute_bytype(dh2
, CKA_VALUE
);
295 if ((attr1
== NULL
) && (attr2
== NULL
))
297 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
298 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
299 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
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
)))
310 if (!dh1
->ontoken
&& !dh2
->ontoken
)
312 else if (dh1
->ontoken
|| dh2
->ontoken
||
313 (dh1
->object
!= dh2
->object
))
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
))
329 else if ((dh1
== NULL
) || (dh2
== NULL
))
332 attr1
= pk11_attribute_bytype(dh1
, CKA_PRIME
);
333 attr2
= pk11_attribute_bytype(dh2
, CKA_PRIME
);
334 if ((attr1
== NULL
) && (attr2
== NULL
))
336 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
337 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
338 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
341 attr1
= pk11_attribute_bytype(dh1
, CKA_BASE
);
342 attr2
= pk11_attribute_bytype(dh2
, CKA_BASE
);
343 if ((attr1
== NULL
) && (attr2
== NULL
))
345 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
346 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
347 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
354 pkcs11dh_generate(dst_key_t
*key
, int generator
, void (*callback
)(int)) {
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
;
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
) },
398 pk11_object_t
*dh
= NULL
;
399 pk11_context_t
*pk11_ctx
;
404 pk11_ctx
= (pk11_context_t
*) isc_mem_get(key
->mctx
,
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
)
413 bits
= key
->key_size
;
414 if ((generator
== 0) &&
415 ((bits
== 768) || (bits
== 1024) || (bits
== 1536))) {
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
);
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
);
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,
486 DST_R_CRYPTOFAILURE
);
488 dh
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*dh
));
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);
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
;
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
);
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
);
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
,
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
,
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
));
588 pkcs11dh_isprivate(const dst_key_t
*key
) {
589 pk11_object_t
*dh
= key
->keydata
.pkey
;
594 attr
= pk11_attribute_bytype(dh
, CKA_VALUE2
);
595 return (ISC_TF((attr
!= NULL
) || dh
->ontoken
));
599 pkcs11dh_destroy(dst_key_t
*key
) {
600 pk11_object_t
*dh
= key
->keydata
.pkey
;
606 INSIST((dh
->object
== CK_INVALID_HANDLE
) || dh
->ontoken
);
608 for (attr
= pk11_attribute_first(dh
);
610 attr
= pk11_attribute_next(dh
, attr
))
611 switch (attr
->type
) {
616 if (attr
->pValue
!= NULL
) {
617 memset(attr
->pValue
, 0, attr
->ulValueLen
);
618 isc_mem_put(key
->mctx
,
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
;
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);
642 uint16_fromregion(isc_region_t
*region
) {
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);
655 pkcs11dh_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
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
);
668 attr
= pk11_attribute_next(dh
, attr
))
669 switch (attr
->type
) {
671 pub
= (CK_BYTE
*) attr
->pValue
;
672 publen
= (isc_uint16_t
) attr
->ulValueLen
;
675 prime
= (CK_BYTE
*) attr
->pValue
;
676 plen
= (isc_uint16_t
) attr
->ulValueLen
;
679 base
= (CK_BYTE
*) attr
->pValue
;
680 glen
= (isc_uint16_t
) attr
->ulValueLen
;
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)))) {
698 dnslen
= plen
+ glen
+ publen
+ 6;
699 if (r
.length
< (unsigned int) dnslen
)
700 return (ISC_R_NOSPACE
);
702 uint16_toregion(plen
, &r
);
704 if (memcmp(pk11_dh_bn768
, prime
, sizeof(pk11_dh_bn768
)) == 0)
706 else if (memcmp(pk11_dh_bn1024
, prime
,
707 sizeof(pk11_dh_bn1024
)) == 0)
713 memmove(r
.base
, prime
, plen
);
714 isc_region_consume(&r
, plen
);
716 uint16_toregion(glen
, &r
);
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
);
731 pkcs11dh_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
734 isc_uint16_t plen
, glen
, plen_
, glen_
, publen
;
735 CK_BYTE
*prime
= NULL
, *base
= NULL
, *pub
= NULL
;
739 isc_buffer_remainingregion(data
, &r
);
741 return (ISC_R_SUCCESS
);
743 dh
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*dh
));
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.
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
);
769 if (plen
== 1 || plen
== 2) {
772 isc_region_consume(&r
, 1);
774 special
= uint16_fromregion(&r
);
778 prime
= pk11_dh_bn768
;
779 plen_
= sizeof(pk11_dh_bn768
);
782 prime
= pk11_dh_bn1024
;
783 plen_
= sizeof(pk11_dh_bn1024
);
786 prime
= pk11_dh_bn1536
;
787 plen_
= sizeof(pk11_dh_bn1536
);
790 memset(dh
, 0, sizeof(*dh
));
791 isc_mem_put(key
->mctx
, dh
, sizeof(*dh
));
792 return (DST_R_INVALIDPUBLICKEY
);
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.
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
);
820 glen_
= sizeof(pk11_dh_bn2
);
824 if (memcmp(base
, pk11_dh_bn2
, glen
) == 0) {
826 glen_
= sizeof(pk11_dh_bn2
);
829 memset(dh
, 0, sizeof(*dh
));
830 isc_mem_put(key
->mctx
, dh
, sizeof(*dh
));
831 return (DST_R_INVALIDPUBLICKEY
);
837 memset(dh
, 0, sizeof(*dh
));
838 isc_mem_put(key
->mctx
, dh
, sizeof(*dh
));
839 return (DST_R_INVALIDPUBLICKEY
);
843 isc_region_consume(&r
, glen
);
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
);
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
)
864 memset(dh
->repr
, 0, sizeof(*attr
) * 3);
868 attr
[0].type
= CKA_PRIME
;
869 attr
[0].pValue
= isc_mem_get(key
->mctx
, plen_
);
870 if (attr
[0].pValue
== NULL
)
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
)
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
)
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
);
896 for (attr
= pk11_attribute_first(dh
);
898 attr
= pk11_attribute_next(dh
, attr
))
899 switch (attr
->type
) {
903 if (attr
->pValue
!= NULL
) {
904 memset(attr
->pValue
, 0, attr
->ulValueLen
);
905 isc_mem_put(key
->mctx
,
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
);
921 pkcs11dh_tofile(const dst_key_t
*key
, const char *directory
) {
925 CK_ATTRIBUTE
*prime
= NULL
, *base
= NULL
, *pub
= NULL
, *prv
= NULL
;
927 unsigned char *bufs
[4];
930 if (key
->keydata
.pkey
== NULL
)
931 return (DST_R_NULLKEY
);
934 return (DST_R_EXTERNALKEY
);
936 dh
= key
->keydata
.pkey
;
938 for (attr
= pk11_attribute_first(dh
);
940 attr
= pk11_attribute_next(dh
, attr
))
941 switch (attr
->type
) {
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
;
966 memset(bufs
[i
], 0, prime
->ulValueLen
);
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
];
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
];
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
];
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
];
996 result
= dst__privstruct_writefile(key
, &priv
, directory
);
998 for (i
= 0; i
< 4; i
++) {
1001 memset(bufs
[i
], 0, prime
->ulValueLen
);
1002 isc_mem_put(key
->mctx
, bufs
[i
], prime
->ulValueLen
);
1008 pkcs11dh_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
1012 pk11_object_t
*dh
= NULL
;
1019 /* read private key file */
1020 ret
= dst__privstruct_parse(key
, DST_ALG_DH
, lexer
, mctx
, &priv
);
1021 if (ret
!= ISC_R_SUCCESS
)
1025 DST_RET(DST_R_EXTERNALKEY
);
1027 dh
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*dh
));
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);
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
++) {
1046 bn
= isc_mem_get(key
->mctx
, priv
.elements
[i
].length
);
1048 DST_RET(ISC_R_NOMEMORY
);
1049 memmove(bn
, priv
.elements
[i
].data
, priv
.elements
[i
].length
);
1051 switch (priv
.elements
[i
].tag
) {
1053 attr
= pk11_attribute_bytype(dh
, CKA_PRIME
);
1054 INSIST(attr
!= NULL
);
1056 attr
->ulValueLen
= priv
.elements
[i
].length
;
1058 case TAG_DH_GENERATOR
:
1059 attr
= pk11_attribute_bytype(dh
, CKA_BASE
);
1060 INSIST(attr
!= NULL
);
1062 attr
->ulValueLen
= priv
.elements
[i
].length
;
1064 case TAG_DH_PRIVATE
:
1065 attr
= pk11_attribute_bytype(dh
, CKA_VALUE2
);
1066 INSIST(attr
!= NULL
);
1068 attr
->ulValueLen
= priv
.elements
[i
].length
;
1071 attr
= pk11_attribute_bytype(dh
, CKA_VALUE
);
1072 INSIST(attr
!= NULL
);
1074 attr
->ulValueLen
= priv
.elements
[i
].length
;
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
);
1087 pkcs11dh_destroy(key
);
1088 dst__privstruct_free(&priv
, mctx
);
1089 memset(&priv
, 0, sizeof(priv
));
1093 static dst_func_t pkcs11dh_functions
= {
1094 NULL
, /*%< createctx */
1095 NULL
, /*%< createctx2 */
1096 NULL
, /*%< destroyctx */
1097 NULL
, /*%< adddata */
1099 NULL
, /*%< verify */
1100 NULL
, /*%< verify2 */
1101 pkcs11dh_computesecret
,
1103 pkcs11dh_paramcompare
,
1111 NULL
, /*%< cleanup */
1112 NULL
, /*%< fromlabel */
1114 NULL
, /*%< restore */
1118 dst__pkcs11dh_init(dst_func_t
**funcp
) {
1119 REQUIRE(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 */