Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / pkcs11rsa_link.c
blob916e363271eb64a778bbef1e309ff9a19afaaff9
1 /* $NetBSD: pkcs11rsa_link.c,v 1.1.1.5 2015/09/03 07:21:37 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 /* Id */
21 #ifdef PKCS11CRYPTO
23 #include <config.h>
25 #include <isc/entropy.h>
26 #include <isc/md5.h>
27 #include <isc/sha1.h>
28 #include <isc/sha2.h>
29 #include <isc/mem.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
33 #include <dst/result.h>
35 #include "dst_internal.h"
36 #include "dst_parse.h"
37 #include "dst_pkcs11.h"
39 #include <pk11/internal.h>
42 * Limit the size of public exponents.
44 #ifndef RSA_MAX_PUBEXP_BITS
45 #define RSA_MAX_PUBEXP_BITS 35
46 #endif
48 #define DST_RET(a) {ret = a; goto err;}
50 static CK_BBOOL truevalue = TRUE;
51 static CK_BBOOL falsevalue = FALSE;
53 static isc_result_t pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data);
54 static void pkcs11rsa_destroy(dst_key_t *key);
55 static isc_result_t pkcs11rsa_fetch(dst_key_t *key, const char *engine,
56 const char *label, dst_key_t *pub);
58 static isc_result_t
59 pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
60 CK_RV rv;
61 CK_MECHANISM mech = { 0, NULL, 0 };
62 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
63 CK_KEY_TYPE keyType = CKK_RSA;
64 CK_ATTRIBUTE keyTemplate[] =
66 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
67 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
68 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
69 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
70 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
71 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
72 { CKA_MODULUS, NULL, 0 },
73 { CKA_PUBLIC_EXPONENT, NULL, 0 },
74 { CKA_PRIVATE_EXPONENT, NULL, 0 },
75 { CKA_PRIME_1, NULL, 0 },
76 { CKA_PRIME_2, NULL, 0 },
77 { CKA_EXPONENT_1, NULL, 0 },
78 { CKA_EXPONENT_2, NULL, 0 },
79 { CKA_COEFFICIENT, NULL, 0 }
81 CK_ATTRIBUTE *attr;
82 CK_SLOT_ID slotid;
83 pk11_object_t *rsa;
84 pk11_context_t *pk11_ctx;
85 isc_result_t ret;
86 unsigned int i;
88 REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
89 key->key_alg == DST_ALG_RSASHA1 ||
90 key->key_alg == DST_ALG_NSEC3RSASHA1 ||
91 key->key_alg == DST_ALG_RSASHA256 ||
92 key->key_alg == DST_ALG_RSASHA512);
94 rsa = key->keydata.pkey;
96 pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
97 sizeof(*pk11_ctx));
98 if (pk11_ctx == NULL)
99 return (ISC_R_NOMEMORY);
100 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
101 if (rsa->ontoken)
102 slotid = rsa->slot;
103 else
104 slotid = pk11_get_best_token(OP_RSA);
105 ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
106 rsa->reqlogon, NULL, slotid);
107 if (ret != ISC_R_SUCCESS)
108 goto err;
110 if (rsa->ontoken && (rsa->object != CK_INVALID_HANDLE)) {
111 pk11_ctx->ontoken = rsa->ontoken;
112 pk11_ctx->object = rsa->object;
113 goto token_key;
116 for (attr = pk11_attribute_first(rsa);
117 attr != NULL;
118 attr = pk11_attribute_next(rsa, attr))
119 switch (attr->type) {
120 case CKA_MODULUS:
121 INSIST(keyTemplate[6].type == attr->type);
122 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
123 attr->ulValueLen);
124 if (keyTemplate[6].pValue == NULL)
125 DST_RET(ISC_R_NOMEMORY);
126 memmove(keyTemplate[6].pValue, attr->pValue,
127 attr->ulValueLen);
128 keyTemplate[6].ulValueLen = attr->ulValueLen;
129 break;
130 case CKA_PUBLIC_EXPONENT:
131 INSIST(keyTemplate[7].type == attr->type);
132 keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
133 attr->ulValueLen);
134 if (keyTemplate[7].pValue == NULL)
135 DST_RET(ISC_R_NOMEMORY);
136 memmove(keyTemplate[7].pValue, attr->pValue,
137 attr->ulValueLen);
138 keyTemplate[7].ulValueLen = attr->ulValueLen;
139 break;
140 case CKA_PRIVATE_EXPONENT:
141 INSIST(keyTemplate[8].type == attr->type);
142 keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
143 attr->ulValueLen);
144 if (keyTemplate[8].pValue == NULL)
145 DST_RET(ISC_R_NOMEMORY);
146 memmove(keyTemplate[8].pValue, attr->pValue,
147 attr->ulValueLen);
148 keyTemplate[8].ulValueLen = attr->ulValueLen;
149 break;
150 case CKA_PRIME_1:
151 INSIST(keyTemplate[9].type == attr->type);
152 keyTemplate[9].pValue = isc_mem_get(dctx->mctx,
153 attr->ulValueLen);
154 if (keyTemplate[9].pValue == NULL)
155 DST_RET(ISC_R_NOMEMORY);
156 memmove(keyTemplate[9].pValue, attr->pValue,
157 attr->ulValueLen);
158 keyTemplate[9].ulValueLen = attr->ulValueLen;
159 break;
160 case CKA_PRIME_2:
161 INSIST(keyTemplate[10].type == attr->type);
162 keyTemplate[10].pValue = isc_mem_get(dctx->mctx,
163 attr->ulValueLen);
164 if (keyTemplate[10].pValue == NULL)
165 DST_RET(ISC_R_NOMEMORY);
166 memmove(keyTemplate[10].pValue, attr->pValue,
167 attr->ulValueLen);
168 keyTemplate[10].ulValueLen = attr->ulValueLen;
169 break;
170 case CKA_EXPONENT_1:
171 INSIST(keyTemplate[11].type == attr->type);
172 keyTemplate[11].pValue = isc_mem_get(dctx->mctx,
173 attr->ulValueLen);
174 if (keyTemplate[11].pValue == NULL)
175 DST_RET(ISC_R_NOMEMORY);
176 memmove(keyTemplate[11].pValue, attr->pValue,
177 attr->ulValueLen);
178 keyTemplate[11].ulValueLen = attr->ulValueLen;
179 break;
180 case CKA_EXPONENT_2:
181 INSIST(keyTemplate[12].type == attr->type);
182 keyTemplate[12].pValue = isc_mem_get(dctx->mctx,
183 attr->ulValueLen);
184 if (keyTemplate[12].pValue == NULL)
185 DST_RET(ISC_R_NOMEMORY);
186 memmove(keyTemplate[12].pValue, attr->pValue,
187 attr->ulValueLen);
188 keyTemplate[12].ulValueLen = attr->ulValueLen;
189 break;
190 case CKA_COEFFICIENT:
191 INSIST(keyTemplate[13].type == attr->type);
192 keyTemplate[13].pValue = isc_mem_get(dctx->mctx,
193 attr->ulValueLen);
194 if (keyTemplate[13].pValue == NULL)
195 DST_RET(ISC_R_NOMEMORY);
196 memmove(keyTemplate[13].pValue, attr->pValue,
197 attr->ulValueLen);
198 keyTemplate[13].ulValueLen = attr->ulValueLen;
199 break;
201 pk11_ctx->object = CK_INVALID_HANDLE;
202 pk11_ctx->ontoken = ISC_FALSE;
203 PK11_RET(pkcs_C_CreateObject,
204 (pk11_ctx->session,
205 keyTemplate, (CK_ULONG) 14,
206 &pk11_ctx->object),
207 ISC_R_FAILURE);
209 token_key:
211 switch (dctx->key->key_alg) {
212 case DST_ALG_RSAMD5:
213 mech.mechanism = CKM_MD5_RSA_PKCS;
214 break;
215 case DST_ALG_RSASHA1:
216 case DST_ALG_NSEC3RSASHA1:
217 mech.mechanism = CKM_SHA1_RSA_PKCS;
218 break;
219 case DST_ALG_RSASHA256:
220 mech.mechanism = CKM_SHA256_RSA_PKCS;
221 break;
222 case DST_ALG_RSASHA512:
223 mech.mechanism = CKM_SHA512_RSA_PKCS;
224 break;
225 default:
226 INSIST(0);
229 PK11_RET(pkcs_C_SignInit,
230 (pk11_ctx->session, &mech, pk11_ctx->object),
231 ISC_R_FAILURE);
233 dctx->ctxdata.pk11_ctx = pk11_ctx;
235 for (i = 6; i <= 13; i++)
236 if (keyTemplate[i].pValue != NULL) {
237 memset(keyTemplate[i].pValue, 0,
238 keyTemplate[i].ulValueLen);
239 isc_mem_put(dctx->mctx,
240 keyTemplate[i].pValue,
241 keyTemplate[i].ulValueLen);
244 return (ISC_R_SUCCESS);
246 err:
247 if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
248 (void) pkcs_C_DestroyObject(pk11_ctx->session,
249 pk11_ctx->object);
250 for (i = 6; i <= 13; i++)
251 if (keyTemplate[i].pValue != NULL) {
252 memset(keyTemplate[i].pValue, 0,
253 keyTemplate[i].ulValueLen);
254 isc_mem_put(dctx->mctx,
255 keyTemplate[i].pValue,
256 keyTemplate[i].ulValueLen);
258 pk11_return_session(pk11_ctx);
259 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
260 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
262 return (ret);
265 static isc_result_t
266 pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
267 dst_context_t *dctx) {
268 CK_RV rv;
269 CK_MECHANISM mech = { 0, NULL, 0 };
270 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
271 CK_KEY_TYPE keyType = CKK_RSA;
272 CK_ATTRIBUTE keyTemplate[] =
274 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
275 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
276 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
277 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
278 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
279 { CKA_MODULUS, NULL, 0 },
280 { CKA_PUBLIC_EXPONENT, NULL, 0 },
282 CK_ATTRIBUTE *attr;
283 pk11_object_t *rsa;
284 pk11_context_t *pk11_ctx;
285 isc_result_t ret;
286 unsigned int i;
288 REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
289 key->key_alg == DST_ALG_RSASHA1 ||
290 key->key_alg == DST_ALG_NSEC3RSASHA1 ||
291 key->key_alg == DST_ALG_RSASHA256 ||
292 key->key_alg == DST_ALG_RSASHA512);
294 rsa = key->keydata.pkey;
296 pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
297 sizeof(*pk11_ctx));
298 if (pk11_ctx == NULL)
299 return (ISC_R_NOMEMORY);
300 ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
301 rsa->reqlogon, NULL,
302 pk11_get_best_token(OP_RSA));
303 if (ret != ISC_R_SUCCESS)
304 goto err;
306 for (attr = pk11_attribute_first(rsa);
307 attr != NULL;
308 attr = pk11_attribute_next(rsa, attr))
309 switch (attr->type) {
310 case CKA_MODULUS:
311 INSIST(keyTemplate[5].type == attr->type);
312 keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
313 attr->ulValueLen);
314 if (keyTemplate[5].pValue == NULL)
315 DST_RET(ISC_R_NOMEMORY);
316 memmove(keyTemplate[5].pValue, attr->pValue,
317 attr->ulValueLen);
318 keyTemplate[5].ulValueLen = attr->ulValueLen;
319 break;
320 case CKA_PUBLIC_EXPONENT:
321 INSIST(keyTemplate[6].type == attr->type);
322 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
323 attr->ulValueLen);
324 if (keyTemplate[6].pValue == NULL)
325 DST_RET(ISC_R_NOMEMORY);
326 memmove(keyTemplate[6].pValue, attr->pValue,
327 attr->ulValueLen);
328 keyTemplate[6].ulValueLen = attr->ulValueLen;
329 if (pk11_numbits(attr->pValue,
330 attr->ulValueLen) > maxbits &&
331 maxbits != 0)
332 DST_RET(DST_R_VERIFYFAILURE);
333 break;
335 pk11_ctx->object = CK_INVALID_HANDLE;
336 pk11_ctx->ontoken = ISC_FALSE;
337 PK11_RET(pkcs_C_CreateObject,
338 (pk11_ctx->session,
339 keyTemplate, (CK_ULONG) 7,
340 &pk11_ctx->object),
341 ISC_R_FAILURE);
343 switch (dctx->key->key_alg) {
344 case DST_ALG_RSAMD5:
345 mech.mechanism = CKM_MD5_RSA_PKCS;
346 break;
347 case DST_ALG_RSASHA1:
348 case DST_ALG_NSEC3RSASHA1:
349 mech.mechanism = CKM_SHA1_RSA_PKCS;
350 break;
351 case DST_ALG_RSASHA256:
352 mech.mechanism = CKM_SHA256_RSA_PKCS;
353 break;
354 case DST_ALG_RSASHA512:
355 mech.mechanism = CKM_SHA512_RSA_PKCS;
356 break;
357 default:
358 INSIST(0);
361 PK11_RET(pkcs_C_VerifyInit,
362 (pk11_ctx->session, &mech, pk11_ctx->object),
363 ISC_R_FAILURE);
365 dctx->ctxdata.pk11_ctx = pk11_ctx;
367 for (i = 5; i <= 6; i++)
368 if (keyTemplate[i].pValue != NULL) {
369 memset(keyTemplate[i].pValue, 0,
370 keyTemplate[i].ulValueLen);
371 isc_mem_put(dctx->mctx,
372 keyTemplate[i].pValue,
373 keyTemplate[i].ulValueLen);
376 return (ISC_R_SUCCESS);
378 err:
379 if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
380 (void) pkcs_C_DestroyObject(pk11_ctx->session,
381 pk11_ctx->object);
382 for (i = 5; i <= 6; i++)
383 if (keyTemplate[i].pValue != NULL) {
384 memset(keyTemplate[i].pValue, 0,
385 keyTemplate[i].ulValueLen);
386 isc_mem_put(dctx->mctx,
387 keyTemplate[i].pValue,
388 keyTemplate[i].ulValueLen);
390 pk11_return_session(pk11_ctx);
391 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
392 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
394 return (ret);
397 static isc_result_t
398 pkcs11rsa_createctx(dst_key_t *key, dst_context_t *dctx) {
399 if (dctx->use == DO_SIGN)
400 return (pkcs11rsa_createctx_sign(key, dctx));
401 else
402 return (pkcs11rsa_createctx_verify(key, 0U, dctx));
405 static isc_result_t
406 pkcs11rsa_createctx2(dst_key_t *key, int maxbits, dst_context_t *dctx) {
407 if (dctx->use == DO_SIGN)
408 return (pkcs11rsa_createctx_sign(key, dctx));
409 else
410 return (pkcs11rsa_createctx_verify(key,
411 (unsigned) maxbits, dctx));
414 static void
415 pkcs11rsa_destroyctx(dst_context_t *dctx) {
416 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
418 if (pk11_ctx != NULL) {
419 if (!pk11_ctx->ontoken &&
420 (pk11_ctx->object != CK_INVALID_HANDLE))
421 (void) pkcs_C_DestroyObject(pk11_ctx->session,
422 pk11_ctx->object);
423 pk11_return_session(pk11_ctx);
424 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
425 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
426 dctx->ctxdata.pk11_ctx = NULL;
430 static isc_result_t
431 pkcs11rsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
432 CK_RV rv;
433 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
434 isc_result_t ret = ISC_R_SUCCESS;
436 if (dctx->use == DO_SIGN)
437 PK11_CALL(pkcs_C_SignUpdate,
438 (pk11_ctx->session,
439 (CK_BYTE_PTR) data->base,
440 (CK_ULONG) data->length),
441 ISC_R_FAILURE);
442 else
443 PK11_CALL(pkcs_C_VerifyUpdate,
444 (pk11_ctx->session,
445 (CK_BYTE_PTR) data->base,
446 (CK_ULONG) data->length),
447 ISC_R_FAILURE);
448 return (ret);
451 static isc_result_t
452 pkcs11rsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
453 CK_RV rv;
454 CK_ULONG siglen = 0;
455 isc_region_t r;
456 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
457 isc_result_t ret = ISC_R_SUCCESS;
459 PK11_RET(pkcs_C_SignFinal,
460 (pk11_ctx->session, NULL, &siglen),
461 DST_R_SIGNFAILURE);
463 isc_buffer_availableregion(sig, &r);
465 if (r.length < (unsigned int) siglen)
466 return (ISC_R_NOSPACE);
468 PK11_RET(pkcs_C_SignFinal,
469 (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen),
470 DST_R_SIGNFAILURE);
472 isc_buffer_add(sig, (unsigned int) siglen);
474 err:
475 return (ret);
478 static isc_result_t
479 pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
480 CK_RV rv;
481 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
482 isc_result_t ret = ISC_R_SUCCESS;
484 PK11_CALL(pkcs_C_VerifyFinal,
485 (pk11_ctx->session,
486 (CK_BYTE_PTR) sig->base,
487 (CK_ULONG) sig->length),
488 DST_R_VERIFYFAILURE);
489 return (ret);
492 static isc_boolean_t
493 pkcs11rsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
494 pk11_object_t *rsa1, *rsa2;
495 CK_ATTRIBUTE *attr1, *attr2;
497 rsa1 = key1->keydata.pkey;
498 rsa2 = key2->keydata.pkey;
500 if ((rsa1 == NULL) && (rsa2 == NULL))
501 return (ISC_TRUE);
502 else if ((rsa1 == NULL) || (rsa2 == NULL))
503 return (ISC_FALSE);
505 attr1 = pk11_attribute_bytype(rsa1, CKA_MODULUS);
506 attr2 = pk11_attribute_bytype(rsa2, CKA_MODULUS);
507 if ((attr1 == NULL) && (attr2 == NULL))
508 return (ISC_TRUE);
509 else if ((attr1 == NULL) || (attr2 == NULL) ||
510 (attr1->ulValueLen != attr2->ulValueLen) ||
511 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
512 return (ISC_FALSE);
514 attr1 = pk11_attribute_bytype(rsa1, CKA_PUBLIC_EXPONENT);
515 attr2 = pk11_attribute_bytype(rsa2, CKA_PUBLIC_EXPONENT);
516 if ((attr1 == NULL) && (attr2 == NULL))
517 return (ISC_TRUE);
518 else if ((attr1 == NULL) || (attr2 == NULL) ||
519 (attr1->ulValueLen != attr2->ulValueLen) ||
520 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
521 return (ISC_FALSE);
523 attr1 = pk11_attribute_bytype(rsa1, CKA_PRIVATE_EXPONENT);
524 attr2 = pk11_attribute_bytype(rsa2, CKA_PRIVATE_EXPONENT);
525 if (((attr1 != NULL) || (attr2 != NULL)) &&
526 ((attr1 == NULL) || (attr2 == NULL) ||
527 (attr1->ulValueLen != attr2->ulValueLen) ||
528 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
529 return (ISC_FALSE);
531 if (!rsa1->ontoken && !rsa2->ontoken)
532 return (ISC_TRUE);
533 else if (rsa1->ontoken || rsa2->ontoken ||
534 (rsa1->object != rsa2->object))
535 return (ISC_FALSE);
537 return (ISC_TRUE);
540 static isc_result_t
541 pkcs11rsa_generate(dst_key_t *key, int exp, void (*callback)(int)) {
542 CK_RV rv;
543 CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
544 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
545 CK_ULONG bits = 0;
546 CK_BYTE pubexp[5];
547 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
548 CK_KEY_TYPE keyType = CKK_RSA;
549 CK_ATTRIBUTE pubTemplate[] =
551 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
552 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
553 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
554 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
555 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
556 { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) },
557 { CKA_PUBLIC_EXPONENT, &pubexp, (CK_ULONG) sizeof(pubexp) }
559 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
560 CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
561 CK_ATTRIBUTE privTemplate[] =
563 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
564 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
565 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
566 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
567 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
568 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
569 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
571 CK_ATTRIBUTE *attr;
572 pk11_object_t *rsa;
573 pk11_context_t *pk11_ctx;
574 isc_result_t ret;
575 unsigned int i;
577 UNUSED(callback);
579 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
580 sizeof(*pk11_ctx));
581 if (pk11_ctx == NULL)
582 return (ISC_R_NOMEMORY);
583 ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
584 ISC_FALSE, NULL, pk11_get_best_token(OP_RSA));
585 if (ret != ISC_R_SUCCESS)
586 goto err;
588 bits = key->key_size;
589 if (exp == 0) {
590 /* RSA_F4 0x10001 */
591 pubexp[0] = 1;
592 pubexp[1] = 0;
593 pubexp[2] = 1;
594 pubTemplate[6].ulValueLen = 3;
595 } else {
596 /* F5 0x100000001 */
597 pubexp[0] = 1;
598 pubexp[1] = 0;
599 pubexp[2] = 0;
600 pubexp[3] = 0;
601 pubexp[4] = 1;
602 pubTemplate[6].ulValueLen = 5;
605 PK11_RET(pkcs_C_GenerateKeyPair,
606 (pk11_ctx->session, &mech,
607 pubTemplate, (CK_ULONG) 7,
608 privTemplate, (CK_ULONG) 7,
609 &pub, &priv),
610 DST_R_CRYPTOFAILURE);
612 rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
613 if (rsa == NULL)
614 DST_RET(ISC_R_NOMEMORY);
615 memset(rsa, 0, sizeof(*rsa));
616 key->keydata.pkey = rsa;
617 rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
618 if (rsa->repr == NULL)
619 DST_RET(ISC_R_NOMEMORY);
620 memset(rsa->repr, 0, sizeof(*attr) * 8);
621 rsa->attrcnt = 8;
623 attr = rsa->repr;
624 attr[0].type = CKA_MODULUS;
625 attr[1].type = CKA_PUBLIC_EXPONENT;
626 attr[2].type = CKA_PRIVATE_EXPONENT;
627 attr[3].type = CKA_PRIME_1;
628 attr[4].type = CKA_PRIME_2;
629 attr[5].type = CKA_EXPONENT_1;
630 attr[6].type = CKA_EXPONENT_2;
631 attr[7].type = CKA_COEFFICIENT;
633 PK11_RET(pkcs_C_GetAttributeValue,
634 (pk11_ctx->session, pub, attr, 2),
635 DST_R_CRYPTOFAILURE);
636 for (i = 0; i <= 1; i++) {
637 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
638 if (attr[i].pValue == NULL)
639 DST_RET(ISC_R_NOMEMORY);
640 memset(attr[i].pValue, 0, attr[i].ulValueLen);
642 PK11_RET(pkcs_C_GetAttributeValue,
643 (pk11_ctx->session, pub, attr, 2),
644 DST_R_CRYPTOFAILURE);
646 attr += 2;
647 PK11_RET(pkcs_C_GetAttributeValue,
648 (pk11_ctx->session, priv, attr, 6),
649 DST_R_CRYPTOFAILURE);
650 for (i = 0; i <= 5; i++) {
651 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
652 if (attr[i].pValue == NULL)
653 DST_RET(ISC_R_NOMEMORY);
654 memset(attr[i].pValue, 0, attr[i].ulValueLen);
656 PK11_RET(pkcs_C_GetAttributeValue,
657 (pk11_ctx->session, priv, attr, 6),
658 DST_R_CRYPTOFAILURE);
660 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
661 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
662 pk11_return_session(pk11_ctx);
663 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
664 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
666 return (ISC_R_SUCCESS);
668 err:
669 pkcs11rsa_destroy(key);
670 if (priv != CK_INVALID_HANDLE)
671 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
672 if (pub != CK_INVALID_HANDLE)
673 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
674 pk11_return_session(pk11_ctx);
675 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
676 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
678 return (ret);
681 static isc_boolean_t
682 pkcs11rsa_isprivate(const dst_key_t *key) {
683 pk11_object_t *rsa = key->keydata.pkey;
684 CK_ATTRIBUTE *attr;
686 if (rsa == NULL)
687 return (ISC_FALSE);
688 attr = pk11_attribute_bytype(rsa, CKA_PRIVATE_EXPONENT);
689 return (ISC_TF((attr != NULL) || rsa->ontoken));
692 static void
693 pkcs11rsa_destroy(dst_key_t *key) {
694 pk11_object_t *rsa = key->keydata.pkey;
695 CK_ATTRIBUTE *attr;
697 if (rsa == NULL)
698 return;
700 INSIST((rsa->object == CK_INVALID_HANDLE) || rsa->ontoken);
702 for (attr = pk11_attribute_first(rsa);
703 attr != NULL;
704 attr = pk11_attribute_next(rsa, attr))
705 switch (attr->type) {
706 case CKA_LABEL:
707 case CKA_ID:
708 case CKA_MODULUS:
709 case CKA_PUBLIC_EXPONENT:
710 case CKA_PRIVATE_EXPONENT:
711 case CKA_PRIME_1:
712 case CKA_PRIME_2:
713 case CKA_EXPONENT_1:
714 case CKA_EXPONENT_2:
715 case CKA_COEFFICIENT:
716 if (attr->pValue != NULL) {
717 memset(attr->pValue, 0, attr->ulValueLen);
718 isc_mem_put(key->mctx,
719 attr->pValue,
720 attr->ulValueLen);
722 break;
724 if (rsa->repr != NULL) {
725 memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
726 isc_mem_put(key->mctx,
727 rsa->repr,
728 rsa->attrcnt * sizeof(*attr));
730 memset(rsa, 0, sizeof(*rsa));
731 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
732 key->keydata.pkey = NULL;
735 static isc_result_t
736 pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data) {
737 pk11_object_t *rsa;
738 CK_ATTRIBUTE *attr;
739 isc_region_t r;
740 unsigned int e_bytes = 0, mod_bytes = 0;
741 CK_BYTE *exponent = NULL, *modulus = NULL;
743 REQUIRE(key->keydata.pkey != NULL);
745 rsa = key->keydata.pkey;
747 for (attr = pk11_attribute_first(rsa);
748 attr != NULL;
749 attr = pk11_attribute_next(rsa, attr))
750 switch (attr->type) {
751 case CKA_PUBLIC_EXPONENT:
752 exponent = (CK_BYTE *) attr->pValue;
753 e_bytes = (unsigned int) attr->ulValueLen;
754 break;
755 case CKA_MODULUS:
756 modulus = (CK_BYTE *) attr->pValue;
757 mod_bytes = (unsigned int) attr->ulValueLen;
758 break;
760 REQUIRE((exponent != NULL) && (modulus != NULL));
762 isc_buffer_availableregion(data, &r);
764 if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
765 if (r.length < 1)
766 return (ISC_R_NOSPACE);
767 isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
768 isc_region_consume(&r, 1);
769 } else {
770 if (r.length < 3)
771 return (ISC_R_NOSPACE);
772 isc_buffer_putuint8(data, 0);
773 isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
774 isc_region_consume(&r, 3);
777 if (r.length < e_bytes + mod_bytes)
778 return (ISC_R_NOSPACE);
780 memmove(r.base, exponent, e_bytes);
781 isc_region_consume(&r, e_bytes);
782 memmove(r.base, modulus, mod_bytes);
784 isc_buffer_add(data, e_bytes + mod_bytes);
786 return (ISC_R_SUCCESS);
789 static isc_result_t
790 pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
791 pk11_object_t *rsa;
792 isc_region_t r;
793 unsigned int e_bytes, mod_bytes;
794 CK_BYTE *exponent = NULL, *modulus = NULL;
795 CK_ATTRIBUTE *attr;
796 unsigned int length;
798 isc_buffer_remainingregion(data, &r);
799 if (r.length == 0)
800 return (ISC_R_SUCCESS);
801 length = r.length;
803 rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
804 if (rsa == NULL)
805 return (ISC_R_NOMEMORY);
807 memset(rsa, 0, sizeof(*rsa));
809 e_bytes = *r.base;
810 isc_region_consume(&r, 1);
812 if (e_bytes == 0) {
813 if (r.length < 2) {
814 memset(rsa, 0, sizeof(*rsa));
815 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
816 return (DST_R_INVALIDPUBLICKEY);
818 e_bytes = (*r.base) << 8;
819 isc_region_consume(&r, 1);
820 e_bytes += *r.base;
821 isc_region_consume(&r, 1);
824 if (r.length < e_bytes) {
825 memset(rsa, 0, sizeof(*rsa));
826 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
827 return (DST_R_INVALIDPUBLICKEY);
829 exponent = r.base;
830 isc_region_consume(&r, e_bytes);
831 modulus = r.base;
832 mod_bytes = r.length;
834 key->key_size = pk11_numbits(modulus, mod_bytes);
836 isc_buffer_forward(data, length);
838 rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
839 if (rsa->repr == NULL)
840 goto nomemory;
841 memset(rsa->repr, 0, sizeof(*attr) * 2);
842 rsa->attrcnt = 2;
843 attr = rsa->repr;
844 attr[0].type = CKA_MODULUS;
845 attr[0].pValue = isc_mem_get(key->mctx, mod_bytes);
846 if (attr[0].pValue == NULL)
847 goto nomemory;
848 memmove(attr[0].pValue, modulus, mod_bytes);
849 attr[0].ulValueLen = (CK_ULONG) mod_bytes;
850 attr[1].type = CKA_PUBLIC_EXPONENT;
851 attr[1].pValue = isc_mem_get(key->mctx, e_bytes);
852 if (attr[1].pValue == NULL)
853 goto nomemory;
854 memmove(attr[1].pValue, exponent, e_bytes);
855 attr[1].ulValueLen = (CK_ULONG) e_bytes;
857 key->keydata.pkey = rsa;
859 return (ISC_R_SUCCESS);
861 nomemory:
862 for (attr = pk11_attribute_first(rsa);
863 attr != NULL;
864 attr = pk11_attribute_next(rsa, attr))
865 switch (attr->type) {
866 case CKA_MODULUS:
867 case CKA_PUBLIC_EXPONENT:
868 if (attr->pValue != NULL) {
869 memset(attr->pValue, 0, attr->ulValueLen);
870 isc_mem_put(key->mctx,
871 attr->pValue,
872 attr->ulValueLen);
874 break;
876 if (rsa->repr != NULL) {
877 memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
878 isc_mem_put(key->mctx,
879 rsa->repr,
880 rsa->attrcnt * sizeof(*attr));
882 memset(rsa, 0, sizeof(*rsa));
883 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
884 return (ISC_R_NOMEMORY);
887 static isc_result_t
888 pkcs11rsa_tofile(const dst_key_t *key, const char *directory) {
889 int i;
890 pk11_object_t *rsa;
891 CK_ATTRIBUTE *attr;
892 CK_ATTRIBUTE *modulus = NULL, *exponent = NULL;
893 CK_ATTRIBUTE *d = NULL, *p = NULL, *q = NULL;
894 CK_ATTRIBUTE *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
895 dst_private_t priv;
896 unsigned char *bufs[10];
897 isc_result_t result;
899 if (key->keydata.pkey == NULL)
900 return (DST_R_NULLKEY);
902 if (key->external) {
903 priv.nelements = 0;
904 return (dst__privstruct_writefile(key, &priv, directory));
907 rsa = key->keydata.pkey;
909 for (attr = pk11_attribute_first(rsa);
910 attr != NULL;
911 attr = pk11_attribute_next(rsa, attr))
912 switch (attr->type) {
913 case CKA_MODULUS:
914 modulus = attr;
915 break;
916 case CKA_PUBLIC_EXPONENT:
917 exponent = attr;
918 break;
919 case CKA_PRIVATE_EXPONENT:
920 d = attr;
921 break;
922 case CKA_PRIME_1:
923 p = attr;
924 break;
925 case CKA_PRIME_2:
926 q = attr;
927 break;
928 case CKA_EXPONENT_1:
929 dmp1 = attr;
930 break;
931 case CKA_EXPONENT_2:
932 dmq1 = attr;
933 break;
934 case CKA_COEFFICIENT:
935 iqmp = attr;
936 break;
938 if ((modulus == NULL) || (exponent == NULL))
939 return (DST_R_NULLKEY);
941 memset(bufs, 0, sizeof(bufs));
943 for (i = 0; i < 10; i++) {
944 bufs[i] = isc_mem_get(key->mctx, modulus->ulValueLen);
945 if (bufs[i] == NULL) {
946 result = ISC_R_NOMEMORY;
947 goto fail;
949 memset(bufs[i], 0, modulus->ulValueLen);
952 i = 0;
954 priv.elements[i].tag = TAG_RSA_MODULUS;
955 priv.elements[i].length = (unsigned short) modulus->ulValueLen;
956 memmove(bufs[i], modulus->pValue, modulus->ulValueLen);
957 priv.elements[i].data = bufs[i];
958 i++;
960 priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
961 priv.elements[i].length = (unsigned short) exponent->ulValueLen;
962 memmove(bufs[i], exponent->pValue, exponent->ulValueLen);
963 priv.elements[i].data = bufs[i];
964 i++;
966 if (d != NULL) {
967 priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
968 priv.elements[i].length = (unsigned short) d->ulValueLen;
969 memmove(bufs[i], d->pValue, d->ulValueLen);
970 priv.elements[i].data = bufs[i];
971 i++;
974 if (p != NULL) {
975 priv.elements[i].tag = TAG_RSA_PRIME1;
976 priv.elements[i].length = (unsigned short) p->ulValueLen;
977 memmove(bufs[i], p->pValue, p->ulValueLen);
978 priv.elements[i].data = bufs[i];
979 i++;
982 if (q != NULL) {
983 priv.elements[i].tag = TAG_RSA_PRIME2;
984 priv.elements[i].length = (unsigned short) q->ulValueLen;
985 memmove(bufs[i], q->pValue, q->ulValueLen);
986 priv.elements[i].data = bufs[i];
987 i++;
990 if (dmp1 != NULL) {
991 priv.elements[i].tag = TAG_RSA_EXPONENT1;
992 priv.elements[i].length = (unsigned short) dmp1->ulValueLen;
993 memmove(bufs[i], dmp1->pValue, dmp1->ulValueLen);
994 priv.elements[i].data = bufs[i];
995 i++;
998 if (dmq1 != NULL) {
999 priv.elements[i].tag = TAG_RSA_EXPONENT2;
1000 priv.elements[i].length = (unsigned short) dmq1->ulValueLen;
1001 memmove(bufs[i], dmq1->pValue, dmq1->ulValueLen);
1002 priv.elements[i].data = bufs[i];
1003 i++;
1006 if (iqmp != NULL) {
1007 priv.elements[i].tag = TAG_RSA_COEFFICIENT;
1008 priv.elements[i].length = (unsigned short) iqmp->ulValueLen;
1009 memmove(bufs[i], iqmp->pValue, iqmp->ulValueLen);
1010 priv.elements[i].data = bufs[i];
1011 i++;
1014 if (key->engine != NULL) {
1015 priv.elements[i].tag = TAG_RSA_ENGINE;
1016 priv.elements[i].length = strlen(key->engine) + 1;
1017 priv.elements[i].data = (unsigned char *)key->engine;
1018 i++;
1021 if (key->label != NULL) {
1022 priv.elements[i].tag = TAG_RSA_LABEL;
1023 priv.elements[i].length = strlen(key->label) + 1;
1024 priv.elements[i].data = (unsigned char *)key->label;
1025 i++;
1028 priv.nelements = i;
1029 result = dst__privstruct_writefile(key, &priv, directory);
1030 fail:
1031 for (i = 0; i < 10; i++) {
1032 if (bufs[i] == NULL)
1033 break;
1034 memset(bufs[i], 0, modulus->ulValueLen);
1035 isc_mem_put(key->mctx, bufs[i], modulus->ulValueLen);
1037 return (result);
1040 static isc_result_t
1041 pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
1042 dst_key_t *pub)
1044 CK_RV rv;
1045 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
1046 CK_KEY_TYPE keyType = CKK_RSA;
1047 CK_ATTRIBUTE searchTemplate[] =
1049 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
1050 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
1051 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
1052 { CKA_LABEL, NULL, 0 }
1054 CK_ULONG cnt;
1055 CK_ATTRIBUTE *attr;
1056 CK_ATTRIBUTE *pubattr;
1057 pk11_object_t *rsa;
1058 pk11_object_t *pubrsa;
1059 pk11_context_t *pk11_ctx = NULL;
1060 isc_result_t ret;
1062 if (label == NULL)
1063 return (DST_R_NOENGINE);
1065 rsa = key->keydata.pkey;
1066 pubrsa = pub->keydata.pkey;
1068 rsa->object = CK_INVALID_HANDLE;
1069 rsa->ontoken = ISC_TRUE;
1070 rsa->reqlogon = ISC_TRUE;
1071 rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
1072 if (rsa->repr == NULL)
1073 return (ISC_R_NOMEMORY);
1074 memset(rsa->repr, 0, sizeof(*attr) * 2);
1075 rsa->attrcnt = 2;
1076 attr = rsa->repr;
1078 attr->type = CKA_MODULUS;
1079 pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
1080 attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
1081 if (attr->pValue == NULL)
1082 DST_RET(ISC_R_NOMEMORY);
1083 memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
1084 attr->ulValueLen = pubattr->ulValueLen;
1085 attr++;
1087 attr->type = CKA_PUBLIC_EXPONENT;
1088 pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
1089 attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
1090 if (attr->pValue == NULL)
1091 DST_RET(ISC_R_NOMEMORY);
1092 memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
1093 attr->ulValueLen = pubattr->ulValueLen;
1095 ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
1096 if (ret != ISC_R_SUCCESS)
1097 goto err;
1099 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
1100 sizeof(*pk11_ctx));
1101 if (pk11_ctx == NULL)
1102 DST_RET(ISC_R_NOMEMORY);
1103 ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
1104 rsa->reqlogon, NULL, rsa->slot);
1105 if (ret != ISC_R_SUCCESS)
1106 goto err;
1108 attr = pk11_attribute_bytype(rsa, CKA_LABEL);
1109 if (attr == NULL) {
1110 attr = pk11_attribute_bytype(rsa, CKA_ID);
1111 INSIST(attr != NULL);
1112 searchTemplate[3].type = CKA_ID;
1114 searchTemplate[3].pValue = attr->pValue;
1115 searchTemplate[3].ulValueLen = attr->ulValueLen;
1117 PK11_RET(pkcs_C_FindObjectsInit,
1118 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
1119 DST_R_CRYPTOFAILURE);
1120 PK11_RET(pkcs_C_FindObjects,
1121 (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
1122 DST_R_CRYPTOFAILURE);
1123 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
1124 if (cnt == 0)
1125 DST_RET(ISC_R_NOTFOUND);
1126 if (cnt > 1)
1127 DST_RET(ISC_R_EXISTS);
1129 if (engine != NULL) {
1130 key->engine = isc_mem_strdup(key->mctx, engine);
1131 if (key->engine == NULL)
1132 DST_RET(ISC_R_NOMEMORY);
1135 key->label = isc_mem_strdup(key->mctx, label);
1136 if (key->label == NULL)
1137 DST_RET(ISC_R_NOMEMORY);
1139 pk11_return_session(pk11_ctx);
1140 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
1141 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
1143 attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
1144 INSIST(attr != NULL);
1145 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
1147 return (ISC_R_SUCCESS);
1149 err:
1150 if (pk11_ctx != NULL) {
1151 pk11_return_session(pk11_ctx);
1152 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
1153 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
1156 return (ret);
1159 static isc_result_t
1160 rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) {
1161 CK_ATTRIBUTE *pubattr, *privattr;
1162 CK_BYTE *priv_exp = NULL, *priv_mod = NULL;
1163 CK_BYTE *pub_exp = NULL, *pub_mod = NULL;
1164 unsigned int priv_explen = 0, priv_modlen = 0;
1165 unsigned int pub_explen = 0, pub_modlen = 0;
1167 REQUIRE(rsa != NULL && pubrsa != NULL);
1169 privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
1170 INSIST(privattr != NULL);
1171 priv_exp = privattr->pValue;
1172 priv_explen = privattr->ulValueLen;
1174 pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
1175 INSIST(pubattr != NULL);
1176 pub_exp = pubattr->pValue;
1177 pub_explen = pubattr->ulValueLen;
1179 if (priv_exp != NULL) {
1180 if (priv_explen != pub_explen)
1181 return (DST_R_INVALIDPRIVATEKEY);
1182 if (memcmp(priv_exp, pub_exp, pub_explen) != 0)
1183 return (DST_R_INVALIDPRIVATEKEY);
1184 } else {
1185 privattr->pValue = pub_exp;
1186 privattr->ulValueLen = pub_explen;
1187 pubattr->pValue = NULL;
1188 pubattr->ulValueLen = 0;
1191 if (privattr->pValue == NULL)
1192 return (DST_R_INVALIDPRIVATEKEY);
1194 privattr = pk11_attribute_bytype(rsa, CKA_MODULUS);
1195 INSIST(privattr != NULL);
1196 priv_mod = privattr->pValue;
1197 priv_modlen = privattr->ulValueLen;
1199 pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
1200 INSIST(pubattr != NULL);
1201 pub_mod = pubattr->pValue;
1202 pub_modlen = pubattr->ulValueLen;
1204 if (priv_mod != NULL) {
1205 if (priv_modlen != pub_modlen)
1206 return (DST_R_INVALIDPRIVATEKEY);
1207 if (memcmp(priv_mod, pub_mod, pub_modlen) != 0)
1208 return (DST_R_INVALIDPRIVATEKEY);
1209 } else {
1210 privattr->pValue = pub_mod;
1211 privattr->ulValueLen = pub_modlen;
1212 pubattr->pValue = NULL;
1213 pubattr->ulValueLen = 0;
1216 if (privattr->pValue == NULL)
1217 return (DST_R_INVALIDPRIVATEKEY);
1219 return (ISC_R_SUCCESS);
1222 static isc_result_t
1223 pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1224 dst_private_t priv;
1225 isc_result_t ret;
1226 int i;
1227 pk11_object_t *rsa;
1228 CK_ATTRIBUTE *attr;
1229 isc_mem_t *mctx = key->mctx;
1230 const char *engine = NULL, *label = NULL;
1232 /* read private key file */
1233 ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
1234 if (ret != ISC_R_SUCCESS)
1235 return (ret);
1237 if (key->external) {
1238 if (priv.nelements != 0)
1239 DST_RET(DST_R_INVALIDPRIVATEKEY);
1240 if (pub == NULL)
1241 DST_RET(DST_R_INVALIDPRIVATEKEY);
1243 key->keydata.pkey = pub->keydata.pkey;
1244 pub->keydata.pkey = NULL;
1245 key->key_size = pub->key_size;
1247 dst__privstruct_free(&priv, mctx);
1248 memset(&priv, 0, sizeof(priv));
1250 return (ISC_R_SUCCESS);
1253 for (i = 0; i < priv.nelements; i++) {
1254 switch (priv.elements[i].tag) {
1255 case TAG_RSA_ENGINE:
1256 engine = (char *)priv.elements[i].data;
1257 break;
1258 case TAG_RSA_LABEL:
1259 label = (char *)priv.elements[i].data;
1260 break;
1261 default:
1262 break;
1265 rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
1266 if (rsa == NULL)
1267 DST_RET(ISC_R_NOMEMORY);
1268 memset(rsa, 0, sizeof(*rsa));
1269 key->keydata.pkey = rsa;
1271 /* Is this key is stored in a HSM? See if we can fetch it. */
1272 if ((label != NULL) || (engine != NULL)) {
1273 ret = pkcs11rsa_fetch(key, engine, label, pub);
1274 if (ret != ISC_R_SUCCESS)
1275 goto err;
1276 dst__privstruct_free(&priv, mctx);
1277 memset(&priv, 0, sizeof(priv));
1278 return (ret);
1281 rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
1282 if (rsa->repr == NULL)
1283 DST_RET(ISC_R_NOMEMORY);
1284 memset(rsa->repr, 0, sizeof(*attr) * 8);
1285 rsa->attrcnt = 8;
1286 attr = rsa->repr;
1287 attr[0].type = CKA_MODULUS;
1288 attr[1].type = CKA_PUBLIC_EXPONENT;
1289 attr[2].type = CKA_PRIVATE_EXPONENT;
1290 attr[3].type = CKA_PRIME_1;
1291 attr[4].type = CKA_PRIME_2;
1292 attr[5].type = CKA_EXPONENT_1;
1293 attr[6].type = CKA_EXPONENT_2;
1294 attr[7].type = CKA_COEFFICIENT;
1296 for (i = 0; i < priv.nelements; i++) {
1297 CK_BYTE *bn;
1299 switch (priv.elements[i].tag) {
1300 case TAG_RSA_ENGINE:
1301 continue;
1302 case TAG_RSA_LABEL:
1303 continue;
1304 default:
1305 bn = isc_mem_get(key->mctx, priv.elements[i].length);
1306 if (bn == NULL)
1307 DST_RET(ISC_R_NOMEMORY);
1308 memmove(bn, priv.elements[i].data,
1309 priv.elements[i].length);
1312 switch (priv.elements[i].tag) {
1313 case TAG_RSA_MODULUS:
1314 attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
1315 INSIST(attr != NULL);
1316 attr->pValue = bn;
1317 attr->ulValueLen = priv.elements[i].length;
1318 break;
1319 case TAG_RSA_PUBLICEXPONENT:
1320 attr = pk11_attribute_bytype(rsa,
1321 CKA_PUBLIC_EXPONENT);
1322 INSIST(attr != NULL);
1323 attr->pValue = bn;
1324 attr->ulValueLen = priv.elements[i].length;
1325 break;
1326 case TAG_RSA_PRIVATEEXPONENT:
1327 attr = pk11_attribute_bytype(rsa,
1328 CKA_PRIVATE_EXPONENT);
1329 INSIST(attr != NULL);
1330 attr->pValue = bn;
1331 attr->ulValueLen = priv.elements[i].length;
1332 break;
1333 case TAG_RSA_PRIME1:
1334 attr = pk11_attribute_bytype(rsa, CKA_PRIME_1);
1335 INSIST(attr != NULL);
1336 attr->pValue = bn;
1337 attr->ulValueLen = priv.elements[i].length;
1338 break;
1339 case TAG_RSA_PRIME2:
1340 attr = pk11_attribute_bytype(rsa, CKA_PRIME_2);
1341 INSIST(attr != NULL);
1342 attr->pValue = bn;
1343 attr->ulValueLen = priv.elements[i].length;
1344 break;
1345 case TAG_RSA_EXPONENT1:
1346 attr = pk11_attribute_bytype(rsa,
1347 CKA_EXPONENT_1);
1348 INSIST(attr != NULL);
1349 attr->pValue = bn;
1350 attr->ulValueLen = priv.elements[i].length;
1351 break;
1352 case TAG_RSA_EXPONENT2:
1353 attr = pk11_attribute_bytype(rsa,
1354 CKA_EXPONENT_2);
1355 INSIST(attr != NULL);
1356 attr->pValue = bn;
1357 attr->ulValueLen = priv.elements[i].length;
1358 break;
1359 case TAG_RSA_COEFFICIENT:
1360 attr = pk11_attribute_bytype(rsa,
1361 CKA_COEFFICIENT);
1362 INSIST(attr != NULL);
1363 attr->pValue = bn;
1364 attr->ulValueLen = priv.elements[i].length;
1365 break;
1369 if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS)
1370 DST_RET(DST_R_INVALIDPRIVATEKEY);
1372 attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
1373 INSIST(attr != NULL);
1374 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
1376 attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
1377 INSIST(attr != NULL);
1378 if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
1379 DST_RET(ISC_R_RANGE);
1381 dst__privstruct_free(&priv, mctx);
1382 memset(&priv, 0, sizeof(priv));
1384 return (ISC_R_SUCCESS);
1386 err:
1387 pkcs11rsa_destroy(key);
1388 dst__privstruct_free(&priv, mctx);
1389 memset(&priv, 0, sizeof(priv));
1390 return (ret);
1393 static isc_result_t
1394 pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
1395 const char *pin)
1397 CK_RV rv;
1398 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
1399 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
1400 CK_KEY_TYPE keyType = CKK_RSA;
1401 CK_ATTRIBUTE searchTemplate[] =
1403 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
1404 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
1405 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
1406 { CKA_LABEL, NULL, 0 }
1408 CK_ULONG cnt;
1409 CK_ATTRIBUTE *attr;
1410 pk11_object_t *rsa;
1411 pk11_context_t *pk11_ctx = NULL;
1412 isc_result_t ret;
1413 unsigned int i;
1415 UNUSED(pin);
1417 rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
1418 if (rsa == NULL)
1419 return (ISC_R_NOMEMORY);
1420 memset(rsa, 0, sizeof(*rsa));
1421 rsa->object = CK_INVALID_HANDLE;
1422 rsa->ontoken = ISC_TRUE;
1423 rsa->reqlogon = ISC_TRUE;
1424 key->keydata.pkey = rsa;
1426 rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
1427 if (rsa->repr == NULL)
1428 DST_RET(ISC_R_NOMEMORY);
1429 memset(rsa->repr, 0, sizeof(*attr) * 2);
1430 rsa->attrcnt = 2;
1431 attr = rsa->repr;
1432 attr[0].type = CKA_MODULUS;
1433 attr[1].type = CKA_PUBLIC_EXPONENT;
1435 ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
1436 if (ret != ISC_R_SUCCESS)
1437 goto err;
1439 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
1440 sizeof(*pk11_ctx));
1441 if (pk11_ctx == NULL)
1442 DST_RET(ISC_R_NOMEMORY);
1443 ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
1444 rsa->reqlogon, NULL, rsa->slot);
1445 if (ret != ISC_R_SUCCESS)
1446 goto err;
1448 attr = pk11_attribute_bytype(rsa, CKA_LABEL);
1449 if (attr == NULL) {
1450 attr = pk11_attribute_bytype(rsa, CKA_ID);
1451 INSIST(attr != NULL);
1452 searchTemplate[3].type = CKA_ID;
1454 searchTemplate[3].pValue = attr->pValue;
1455 searchTemplate[3].ulValueLen = attr->ulValueLen;
1457 PK11_RET(pkcs_C_FindObjectsInit,
1458 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
1459 DST_R_CRYPTOFAILURE);
1460 PK11_RET(pkcs_C_FindObjects,
1461 (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
1462 DST_R_CRYPTOFAILURE);
1463 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
1464 if (cnt == 0)
1465 DST_RET(ISC_R_NOTFOUND);
1466 if (cnt > 1)
1467 DST_RET(ISC_R_EXISTS);
1469 attr = rsa->repr;
1470 PK11_RET(pkcs_C_GetAttributeValue,
1471 (pk11_ctx->session, hKey, attr, 2),
1472 DST_R_CRYPTOFAILURE);
1473 for (i = 0; i <= 1; i++) {
1474 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
1475 if (attr[i].pValue == NULL)
1476 DST_RET(ISC_R_NOMEMORY);
1477 memset(attr[i].pValue, 0, attr[i].ulValueLen);
1479 PK11_RET(pkcs_C_GetAttributeValue,
1480 (pk11_ctx->session, hKey, attr, 2),
1481 DST_R_CRYPTOFAILURE);
1483 keyClass = CKO_PRIVATE_KEY;
1484 PK11_RET(pkcs_C_FindObjectsInit,
1485 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
1486 DST_R_CRYPTOFAILURE);
1487 PK11_RET(pkcs_C_FindObjects,
1488 (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
1489 DST_R_CRYPTOFAILURE);
1490 (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
1491 if (cnt == 0)
1492 DST_RET(ISC_R_NOTFOUND);
1493 if (cnt > 1)
1494 DST_RET(ISC_R_EXISTS);
1496 if (engine != NULL) {
1497 key->engine = isc_mem_strdup(key->mctx, engine);
1498 if (key->engine == NULL)
1499 DST_RET(ISC_R_NOMEMORY);
1502 key->label = isc_mem_strdup(key->mctx, label);
1503 if (key->label == NULL)
1504 DST_RET(ISC_R_NOMEMORY);
1506 attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
1507 INSIST(attr != NULL);
1508 if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
1509 DST_RET(ISC_R_RANGE);
1511 attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
1512 INSIST(attr != NULL);
1513 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
1515 pk11_return_session(pk11_ctx);
1516 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
1517 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
1519 return (ISC_R_SUCCESS);
1521 err:
1522 pkcs11rsa_destroy(key);
1523 if (pk11_ctx != NULL) {
1524 pk11_return_session(pk11_ctx);
1525 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
1526 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
1529 return (ret);
1532 static dst_func_t pkcs11rsa_functions = {
1533 pkcs11rsa_createctx,
1534 pkcs11rsa_createctx2,
1535 pkcs11rsa_destroyctx,
1536 pkcs11rsa_adddata,
1537 pkcs11rsa_sign,
1538 pkcs11rsa_verify,
1539 NULL, /*%< verify2 */
1540 NULL, /*%< computesecret */
1541 pkcs11rsa_compare,
1542 NULL, /*%< paramcompare */
1543 pkcs11rsa_generate,
1544 pkcs11rsa_isprivate,
1545 pkcs11rsa_destroy,
1546 pkcs11rsa_todns,
1547 pkcs11rsa_fromdns,
1548 pkcs11rsa_tofile,
1549 pkcs11rsa_parse,
1550 NULL, /*%< cleanup */
1551 pkcs11rsa_fromlabel,
1552 NULL, /*%< dump */
1553 NULL, /*%< restore */
1556 isc_result_t
1557 dst__pkcs11rsa_init(dst_func_t **funcp) {
1558 REQUIRE(funcp != NULL);
1560 if (*funcp == NULL)
1561 *funcp = &pkcs11rsa_functions;
1562 return (ISC_R_SUCCESS);
1565 #else /* PKCS11CRYPTO */
1567 #include <isc/util.h>
1569 EMPTY_TRANSLATION_UNIT
1571 #endif /* PKCS11CRYPTO */
1572 /*! \file */