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