xref: /titanic_41/usr/src/lib/libkmf/libkmf/common/pk11keys.c (revision 1aa8defbaa9c395fdce1fa3a2ae1892b684dfa4f)
1 /*
2  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 /*
6  * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
7  */
8 
9 #include <kmfapiP.h>
10 #include <sha1.h>
11 #include <security/cryptoki.h>
12 
13 #include <ber_der.h>
14 
15 #define	MAX_PUBLIC_KEY_TEMPLATES    (20)
16 #define	MAX_PRIVATE_KEY_TEMPLATES   (24)
17 #define	MAX_SECRET_KEY_TEMPLATES    (24)
18 
19 typedef struct
20 {
21 	KMF_ALGORITHM_INDEX kmfAlgorithmId;
22 	CK_KEY_TYPE ckKeyType;
23 	CK_MECHANISM_TYPE signmech;
24 	CK_MECHANISM_TYPE vfymech;
25 	CK_MECHANISM_TYPE hashmech;
26 } ALG_INFO;
27 
28 static const ALG_INFO alg_info_map[] = {
29 	{ KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, NULL},
30 	{ KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
31 	{ KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 },
32 	{ KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
33 	{ KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 },
34 
35 	/*
36 	 * For RSA, the verify can be done using a single mechanism,
37 	 * but signing must be done separately because not all hardware
38 	 * tokens support the combined hash+key operations.
39 	 */
40 	{ KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS,
41 	    CKM_MD5_RSA_PKCS, CKM_MD5},
42 	{ KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS,
43 	    CKM_SHA1_RSA_PKCS, CKM_SHA_1},
44 	{ KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS,
45 	    CKM_SHA256_RSA_PKCS, CKM_SHA256},
46 	{ KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS,
47 	    CKM_SHA384_RSA_PKCS, CKM_SHA384},
48 	{ KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS,
49 	    CKM_SHA512_RSA_PKCS, CKM_SHA512},
50 	{ KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA,
51 	    CKM_ECDSA, CKM_SHA_1},
52 	{ KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA,
53 	    CKM_ECDSA, CKM_SHA256},
54 	{ KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA,
55 	    CKM_ECDSA, CKM_SHA384},
56 	{ KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA,
57 	    CKM_ECDSA, CKM_SHA512}
58 };
59 
60 KMF_RETURN
get_pk11_data(KMF_ALGORITHM_INDEX AlgId,CK_KEY_TYPE * keytype,CK_MECHANISM_TYPE * signmech,CK_MECHANISM_TYPE * hashmech,boolean_t vfy)61 get_pk11_data(KMF_ALGORITHM_INDEX AlgId,
62 	CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech,
63 	CK_MECHANISM_TYPE *hashmech, boolean_t vfy)
64 {
65 	uint32_t uIndex;
66 	uint32_t uMapSize =
67 	    sizeof (alg_info_map) / sizeof (ALG_INFO);
68 
69 	for (uIndex = 0; uIndex < uMapSize; uIndex++) {
70 		if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) {
71 			if (keytype)
72 				*keytype = alg_info_map[uIndex].ckKeyType;
73 			if (hashmech)
74 				*hashmech = alg_info_map[uIndex].hashmech;
75 			if (signmech)
76 				*signmech =
77 				    (vfy ? alg_info_map[uIndex].vfymech :
78 				    alg_info_map[uIndex].signmech);
79 			return (KMF_OK);
80 		}
81 	}
82 	/* no match */
83 	return (KMF_ERR_BAD_ALGORITHM);
84 }
85 
86 KMF_RETURN
kmf_create_pk11_session(CK_SESSION_HANDLE * sessionp,CK_MECHANISM_TYPE wanted_mech,CK_FLAGS wanted_flags)87 kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp,
88 	CK_MECHANISM_TYPE wanted_mech,
89 	CK_FLAGS wanted_flags)
90 {
91 	CK_RV rv;
92 	KMF_RETURN ret;
93 	KMF_RETURN kmf_rv = KMF_OK;
94 	CK_SLOT_ID_PTR pSlotList;
95 	CK_ULONG pulCount;
96 	CK_MECHANISM_INFO info;
97 	int i;
98 
99 	ret = init_pk11();
100 
101 	if (ret != KMF_OK)
102 		return (ret);
103 
104 	rv = C_GetSlotList(0, NULL, &pulCount);
105 	if (rv != CKR_OK) {
106 		kmf_rv = KMF_ERR_UNINITIALIZED;
107 		goto out;
108 	}
109 
110 	pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
111 	if (pSlotList == NULL) {
112 		kmf_rv = KMF_ERR_MEMORY;
113 		goto out;
114 	}
115 
116 	rv = C_GetSlotList(0, pSlotList, &pulCount);
117 	if (rv != CKR_OK) {
118 		kmf_rv = KMF_ERR_UNINITIALIZED;
119 		goto out;
120 	}
121 
122 	for (i = 0; i < pulCount; i++) {
123 		rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
124 		if (rv == CKR_OK &&
125 		    (info.flags & wanted_flags) == wanted_flags)
126 			break;
127 	}
128 	if (i < pulCount) {
129 		rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
130 		    NULL, NULL, sessionp);
131 
132 		if (rv != CKR_OK) {
133 			kmf_rv = KMF_ERR_UNINITIALIZED;
134 		}
135 	} else {
136 		kmf_rv = KMF_ERR_UNINITIALIZED;
137 	}
138 
139 out:
140 	if (pSlotList != NULL)
141 		free(pSlotList);
142 	return (kmf_rv);
143 
144 }
145 
146 /*
147  * Name: PKCS_AddTemplate
148  *
149  * Description:
150  *  Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
151  *  not expand the array beyond the maximum specified size.
152  *
153  * Returns:
154  *  TRUE - Attribute value succesfully added.
155  *  FALSE - Maximum array size would be exceded.
156  */
157 static int
PKCS_AddTemplate(CK_ATTRIBUTE * pTemplate,CK_ULONG * ckNumTemplates,CK_ULONG ckMaxTemplates,CK_ATTRIBUTE_TYPE ckAttribCode,CK_BYTE * pckBuffer,CK_ULONG ckBufferLen)158 PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
159 	CK_ULONG *ckNumTemplates,
160 	CK_ULONG ckMaxTemplates,
161 	CK_ATTRIBUTE_TYPE ckAttribCode,
162 	CK_BYTE * pckBuffer,
163 	CK_ULONG ckBufferLen)
164 {
165 	if (*ckNumTemplates >= ckMaxTemplates) {
166 		return (FALSE);
167 	}
168 
169 	pTemplate[*ckNumTemplates].type = ckAttribCode;
170 	pTemplate[*ckNumTemplates].pValue = pckBuffer;
171 	pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
172 	(*ckNumTemplates)++;
173 
174 	return (TRUE);
175 }
176 
177 /*
178  * Convert an SPKI data record to PKCS#11
179  * public key object.
180  */
181 static KMF_RETURN
PKCS_CreatePublicKey(const KMF_X509_SPKI * pKey,CK_SESSION_HANDLE ckSession,CK_OBJECT_HANDLE * pckPublicKey)182 PKCS_CreatePublicKey(
183 	const KMF_X509_SPKI *pKey,
184 	CK_SESSION_HANDLE ckSession,
185 	CK_OBJECT_HANDLE *pckPublicKey)
186 {
187 	KMF_RETURN mrReturn = KMF_OK;
188 	CK_RV ckRv;
189 
190 	CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
191 	CK_ULONG ckNumTemplates = 0;
192 
193 	/* Common object attributes */
194 	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
195 	CK_BBOOL ckToken = 0;
196 	CK_BBOOL ckPrivate = 0;
197 
198 	/* Common key attributes */
199 	CK_KEY_TYPE ckKeyType;
200 	CK_BBOOL ckDerive = CK_FALSE;
201 
202 	/* Common public key attributes */
203 	CK_BBOOL ckEncrypt = 1;
204 	CK_BBOOL ckVerify = 1;
205 
206 	CK_BBOOL ckVerifyRecover = CK_FALSE;
207 	CK_BBOOL ckWrap = CK_FALSE;
208 
209 	/* Key part array */
210 	KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
211 	uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
212 	KMF_ALGORITHM_INDEX AlgorithmId;
213 
214 	/* Parse the keyblob */
215 	(void) memset(KeyParts, 0, sizeof (KeyParts));
216 
217 	AlgorithmId = x509_algoid_to_algid(
218 	    (KMF_OID *)&pKey->algorithm.algorithm);
219 	if (AlgorithmId == KMF_ALGID_NONE)
220 		return (KMF_ERR_BAD_ALGORITHM);
221 
222 	mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
223 
224 	if (mrReturn != KMF_OK)
225 		return (mrReturn);
226 
227 	/* Fill in the common object attributes */
228 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
229 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass,
230 	    sizeof (ckObjClass)) ||
231 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
232 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken,
233 	    sizeof (ckToken)) ||
234 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
235 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate,
236 	    sizeof (ckPrivate))) {
237 		mrReturn = KMF_ERR_INTERNAL;
238 		goto cleanup;
239 	}
240 
241 	/* Fill in the common key attributes */
242 	if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) {
243 		goto cleanup;
244 	}
245 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
246 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
247 	    sizeof (ckKeyType)) ||
248 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
249 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive,
250 	    sizeof (ckDerive))) {
251 		mrReturn = KMF_ERR_INTERNAL;
252 		goto cleanup;
253 	}
254 
255 	/* Add common public key attributes */
256 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
257 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt,
258 	    sizeof (ckEncrypt)) ||
259 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
260 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify,
261 	    sizeof (ckVerify)) ||
262 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
263 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER,
264 	    (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) ||
265 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
266 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap,
267 	    sizeof (ckWrap))) {
268 		mrReturn = KMF_ERR_INTERNAL;
269 		goto cleanup;
270 	}
271 
272 	/* Add algorithm specific attributes */
273 	switch (ckKeyType) {
274 	case CKK_RSA:
275 		if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
276 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS,
277 		    (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
278 		    (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
279 
280 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
281 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT,
282 		    (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
283 		    (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) {
284 			mrReturn = KMF_ERR_INTERNAL;
285 			goto cleanup;
286 		}
287 		break;
288 	case CKK_DSA:
289 		if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
290 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME,
291 		    (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data,
292 		    (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) ||
293 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
294 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME,
295 		    (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data,
296 		    (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) ||
297 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
298 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE,
299 		    (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data,
300 		    (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) ||
301 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
302 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE,
303 		    (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data,
304 		    (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) {
305 		mrReturn = KMF_ERR_INTERNAL;
306 		goto cleanup;
307 		}
308 		break;
309 	case CKK_EC:
310 		if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
311 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT,
312 		    (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data,
313 		    (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) ||
314 
315 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
316 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS,
317 		    (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data,
318 		    (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) {
319 			mrReturn = KMF_ERR_INTERNAL;
320 			goto cleanup;
321 		}
322 		break;
323 	default:
324 		mrReturn = KMF_ERR_BAD_PARAMETER;
325 	}
326 
327 	if (mrReturn == KMF_OK) {
328 		/* Instantiate the object */
329 		ckRv = C_CreateObject(ckSession, ckTemplate,
330 		    ckNumTemplates, pckPublicKey);
331 		if (ckRv != CKR_OK)
332 			mrReturn = KMF_ERR_INTERNAL;
333 	}
334 
335 cleanup:
336 	for (i = 0; i < uNumKeyParts; i++) {
337 		kmf_free_data(&KeyParts[i]);
338 	}
339 
340 	return (mrReturn);
341 }
342 
343 /*
344  * PKCS_AcquirePublicKeyHandle
345  *
346  *   Given an assymetric key keyblob, attempts to find the appropriate
347  *    public key.
348  *
349  *  Methods of finding the public key:
350  *  - Public Key with data present:
351  *    Parses the key and creates a temporary session object.
352  *  - Public Key with handle:
353  *    The handle is type converted and returned. Validity of the handle is
354  *    not checked.
355  *  - Public Key with label:
356  *    Attempts to find a public key with the corresponding label.
357  */
358 static KMF_RETURN
PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,const KMF_X509_SPKI * pKey,CK_KEY_TYPE ckRequestedKeyType,CK_OBJECT_HANDLE * pckKeyHandle)359 PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
360 	const KMF_X509_SPKI *pKey,
361 	CK_KEY_TYPE ckRequestedKeyType,
362 	CK_OBJECT_HANDLE *pckKeyHandle)
363 {
364 	KMF_RETURN mrReturn = KMF_OK;
365 
366 	/* Key searching variables */
367 	CK_OBJECT_HANDLE ckKeyHandle = 0;
368 	CK_OBJECT_CLASS ckObjClass;
369 	CK_KEY_TYPE ckKeyType;
370 	CK_ATTRIBUTE ckTemplate[3];
371 	CK_ULONG ckNumTemplates;
372 	static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
373 	    sizeof (CK_ATTRIBUTE));
374 	CK_RV ckRv;
375 
376 	/* Extract the data from the SPKI into individual fields */
377 	mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle);
378 	if (mrReturn != KMF_OK)
379 		return (mrReturn);
380 
381 	/* Fetch the key class and algorithm from the object */
382 	ckNumTemplates = 0;
383 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
384 	    ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass,
385 	    sizeof (ckObjClass)) ||
386 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
387 	    ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
388 	    sizeof (ckKeyType))) {
389 		(void) C_DestroyObject(ckSession, ckKeyHandle);
390 		return (KMF_ERR_INTERNAL);
391 	}
392 	ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
393 	    ckTemplate,	ckNumTemplates);
394 	if (ckRv != CKR_OK) {
395 		(void) C_DestroyObject(ckSession, ckKeyHandle);
396 		return (ckRv);
397 	}
398 
399 	/* Make sure the results match the expected values */
400 	if ((ckKeyType != ckRequestedKeyType) ||
401 	    (ckObjClass != CKO_PUBLIC_KEY)) {
402 		(void) C_DestroyObject(ckSession, ckKeyHandle);
403 		return (KMF_ERR_BAD_KEY_FORMAT);
404 	}
405 
406 	/* Set the return values */
407 	*pckKeyHandle = ckKeyHandle;
408 
409 	return (KMF_OK);
410 }
411 
412 /*
413  * Utility routine for verifying generic data using
414  * the cryptographic framework (PKCS#11).
415  * There are situations where we want to force this
416  * operation to happen in a specific keystore.
417  * For example:
418  * libelfsign.so.1 verifies signatures on crypto libraries.
419  * We must use pkcs11 functions to verify the pkcs11
420  * plugins in order to keep the validation within the
421  * Cryptographic Framework's FIPS-140 boundary. To avoid
422  * a circular dependency, pksc11_softtoken.so.1 is
423  * interposed by libkcfd.so.1 via kcfd, which prevents
424  * libpkcs11.so.1's interfaces from being used when libkmf.so.1
425  * is called from kcfd.
426  *
427  * This also saves code and time because verify operations
428  * only use public keys and do not need acccess to any
429  * keystore specific functions.
430  */
431 KMF_RETURN
PKCS_VerifyData(KMF_HANDLE_T handle,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * data,KMF_DATA * signature)432 PKCS_VerifyData(KMF_HANDLE_T handle,
433 		KMF_ALGORITHM_INDEX AlgorithmId,
434 		KMF_X509_SPKI *keyp,
435 		KMF_DATA *data,
436 		KMF_DATA *signature)
437 {
438 	KMF_RETURN	rv = KMF_OK;
439 	CK_RV		ckRv;
440 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
441 	CK_MECHANISM	ckMechanism;
442 	CK_MECHANISM_TYPE mechtype, hashmech;
443 	CK_OBJECT_HANDLE ckKeyHandle = 0;
444 	CK_KEY_TYPE	pk11keytype;
445 	CK_SESSION_HANDLE ckSession = 0;
446 	CK_ATTRIBUTE	subprime = { CKA_SUBPRIME, NULL, 0 };
447 	CK_BYTE		*dataptr;
448 	CK_ULONG	datalen;
449 	KMF_DATA	hashData = { 0, NULL };
450 	uchar_t		digest[1024];
451 
452 	if (AlgorithmId == KMF_ALGID_NONE)
453 		return (KMF_ERR_BAD_ALGORITHM);
454 
455 	if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1))
456 		return (KMF_ERR_BAD_ALGORITHM);
457 
458 	/*
459 	 * Verify in metaslot/softtoken since only the public key is needed
460 	 * and not all hardware tokens support the combined [hash]-RSA/DSA/EC
461 	 * mechanisms.
462 	 */
463 	rv = kmf_create_pk11_session(&ckSession, mechtype, 0);
464 	if (rv != KMF_OK)
465 		return (rv);
466 
467 	/* Fetch the verifying key */
468 	rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
469 	    pk11keytype, &ckKeyHandle);
470 
471 	if (rv != KMF_OK) {
472 		(void) C_CloseSession(ckSession);
473 		return (rv);
474 	}
475 	dataptr = data->Data;
476 	datalen = data->Length;
477 	/*
478 	 * For some mechanisms, we must compute the hash separately
479 	 * and then do the verify.
480 	 */
481 	if (hashmech != 0 &&
482 	    (mechtype == CKM_ECDSA ||
483 	    mechtype == CKM_DSA ||
484 	    mechtype == CKM_RSA_PKCS)) {
485 		hashData.Data = digest;
486 		hashData.Length = sizeof (digest);
487 
488 		rv = PKCS_DigestData(handle, ckSession,
489 		    hashmech, data, &hashData,
490 		    (mechtype == CKM_RSA_PKCS));
491 		if (rv)
492 			goto cleanup;
493 
494 		dataptr = hashData.Data;
495 		datalen = hashData.Length;
496 	}
497 	if (mechtype == CKM_DSA &&
498 	    hashmech == CKM_SHA256) {
499 		/*
500 		 * FIPS 186-3 says that when using DSA
501 		 * the hash must be truncated to the size of the
502 		 * subprime.
503 		 */
504 		ckRv = C_GetAttributeValue(ckSession,
505 		    ckKeyHandle, &subprime, 1);
506 		if (ckRv != CKR_OK)  {
507 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
508 			kmfh->lasterr.errcode = ckRv;
509 			rv = KMF_ERR_INTERNAL;
510 			goto cleanup;
511 		}
512 		datalen = subprime.ulValueLen;
513 	}
514 
515 	ckMechanism.mechanism = mechtype;
516 	ckMechanism.pParameter = NULL;
517 	ckMechanism.ulParameterLen = 0;
518 
519 	ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
520 	if (ckRv != CKR_OK) {
521 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
522 		kmfh->lasterr.errcode = ckRv;
523 		rv = KMF_ERR_INTERNAL;
524 		goto cleanup;
525 	}
526 	ckRv = C_Verify(ckSession,
527 	    dataptr, datalen,
528 	    (CK_BYTE *)signature->Data,
529 	    (CK_ULONG)signature->Length);
530 
531 	if (ckRv != CKR_OK) {
532 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
533 		kmfh->lasterr.errcode = ckRv;
534 		rv = KMF_ERR_INTERNAL;
535 	}
536 
537 cleanup:
538 	if (ckKeyHandle != 0)
539 		(void) C_DestroyObject(ckSession, ckKeyHandle);
540 	(void) C_CloseSession(ckSession);
541 	return (rv);
542 }
543 
544 KMF_RETURN
PKCS_EncryptData(KMF_HANDLE_T kmfh,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * plaintext,KMF_DATA * ciphertext)545 PKCS_EncryptData(KMF_HANDLE_T kmfh,
546 		KMF_ALGORITHM_INDEX AlgorithmId,
547 		KMF_X509_SPKI *keyp,
548 		KMF_DATA *plaintext,
549 		KMF_DATA *ciphertext)
550 {
551 	KMF_RETURN rv = KMF_OK;
552 	CK_RV ckRv;
553 	CK_MECHANISM ckMechanism;
554 	CK_MECHANISM_TYPE mechtype;
555 	CK_KEY_TYPE keytype;
556 	CK_OBJECT_HANDLE ckKeyHandle = 0;
557 	CK_SESSION_HANDLE ckSession = NULL;
558 	CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
559 	uint8_t *in_data, *out_data;
560 	int i, blocks, block_size;
561 	CK_ATTRIBUTE ckTemplate[2];
562 	CK_ULONG ckNumTemplates;
563 	CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
564 	    sizeof (CK_ATTRIBUTE));
565 
566 	if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0))
567 		return (KMF_ERR_BAD_ALGORITHM);
568 
569 	rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT);
570 	if (rv != KMF_OK)
571 		return (rv);
572 
573 	/* Get the public key used in encryption */
574 	rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
575 	    keytype, &ckKeyHandle);
576 
577 	if (rv != KMF_OK) {
578 		(void) C_CloseSession(ckSession);
579 		return (rv);
580 	}
581 
582 	/* Get the modulus length */
583 	ckNumTemplates = 0;
584 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates,
585 	    CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) {
586 		if (ckKeyHandle != 0)
587 			(void) C_DestroyObject(ckSession, ckKeyHandle);
588 		(void) C_CloseSession(ckSession);
589 		return (KMF_ERR_INTERNAL);
590 	}
591 
592 	ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
593 	    ckTemplate, ckNumTemplates);
594 
595 	if (ckRv != CKR_OK) {
596 		if (ckKeyHandle != 0)
597 			(void) C_DestroyObject(ckSession, ckKeyHandle);
598 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
599 		kmfh->lasterr.errcode = ckRv;
600 		(void) C_CloseSession(ckSession);
601 		return (KMF_ERR_INTERNAL);
602 	}
603 	out_len = ckTemplate[0].ulValueLen;
604 
605 	if (out_len > ciphertext->Length) {
606 		if (ckKeyHandle != 0)
607 			(void) C_DestroyObject(ckSession, ckKeyHandle);
608 		(void) C_CloseSession(ckSession);
609 		return (KMF_ERR_BUFFER_SIZE);
610 	}
611 
612 	ckMechanism.mechanism = mechtype;
613 	ckMechanism.pParameter = NULL_PTR;
614 	ckMechanism.ulParameterLen = 0;
615 
616 	/* Compute the fixed input data length for single-part encryption */
617 	block_size = out_len - 11;
618 
619 	in_data = plaintext->Data;
620 	out_data = ciphertext->Data;
621 
622 	blocks = plaintext->Length/block_size;
623 
624 	for (i = 0; i < blocks; i++) {
625 		ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
626 		if (ckRv != CKR_OK) {
627 			if (ckKeyHandle != 0)
628 				(void) C_DestroyObject(ckSession, ckKeyHandle);
629 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
630 			kmfh->lasterr.errcode = ckRv;
631 			(void) C_CloseSession(ckSession);
632 			return (KMF_ERR_INTERNAL);
633 		}
634 		ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size,
635 		    (CK_BYTE_PTR)out_data, &out_len);
636 
637 		if (ckRv != CKR_OK) {
638 			if (ckKeyHandle != 0)
639 				(void) C_DestroyObject(ckSession, ckKeyHandle);
640 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
641 			kmfh->lasterr.errcode = ckRv;
642 			(void) C_CloseSession(ckSession);
643 			return (KMF_ERR_INTERNAL);
644 		}
645 
646 		out_data += out_len;
647 		total_encrypted += out_len;
648 		in_data += block_size;
649 	}
650 
651 	if (plaintext->Length % block_size) {
652 		/* Encrypt the remaining data */
653 		ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
654 		if (ckRv != CKR_OK) {
655 			if (ckKeyHandle != 0)
656 				(void) C_DestroyObject(ckSession, ckKeyHandle);
657 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
658 			kmfh->lasterr.errcode = ckRv;
659 			(void) C_CloseSession(ckSession);
660 			return (KMF_ERR_INTERNAL);
661 		}
662 
663 		in_len = plaintext->Length % block_size;
664 		ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len,
665 		    (CK_BYTE_PTR)out_data, &out_len);
666 
667 		if (ckRv != CKR_OK) {
668 			if (ckKeyHandle != 0)
669 				(void) C_DestroyObject(ckSession, ckKeyHandle);
670 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
671 			kmfh->lasterr.errcode = ckRv;
672 			(void) C_CloseSession(ckSession);
673 			return (KMF_ERR_INTERNAL);
674 		}
675 
676 		out_data += out_len;
677 		total_encrypted += out_len;
678 		in_data += in_len;
679 	}
680 
681 	ciphertext->Length = total_encrypted;
682 
683 	if (ckKeyHandle != 0)
684 		(void) C_DestroyObject(ckSession, ckKeyHandle);
685 
686 	(void) C_CloseSession(ckSession);
687 	return (rv);
688 
689 }
690 
691 static void
create_id_hash(KMF_DATA * IDInput,KMF_DATA * IDOutput)692 create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput)
693 {
694 	SHA1_CTX ctx;
695 
696 	SHA1Init(&ctx);
697 	SHA1Update(&ctx, IDInput->Data, IDInput->Length);
698 	SHA1Final(IDOutput->Data, &ctx);
699 
700 	IDOutput->Length = SHA1_DIGEST_LENGTH;
701 }
702 
703 KMF_RETURN
GetIDFromSPKI(KMF_X509_SPKI * spki,KMF_DATA * ID)704 GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
705 {
706 	KMF_RETURN rv = KMF_OK;
707 	KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
708 	uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
709 	KMF_ALGORITHM_INDEX algId;
710 	int i;
711 
712 	if (ID == NULL || spki == NULL)
713 		return (KMF_ERR_BAD_PARAMETER);
714 
715 	ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH);
716 	if (ID->Data == NULL)
717 		return (KMF_ERR_MEMORY);
718 
719 	ID->Length = SHA1_HASH_LENGTH;
720 
721 	algId = x509_algoid_to_algid(&spki->algorithm.algorithm);
722 	if (algId == KMF_ALGID_NONE)
723 		return (KMF_ERR_BAD_ALGORITHM);
724 
725 	rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts);
726 	if (rv != KMF_OK)
727 		return (rv);
728 
729 	/* Check the KEY algorithm */
730 	if (algId == KMF_ALGID_RSA) {
731 		create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID);
732 	} else if (algId == KMF_ALGID_DSA) {
733 		create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
734 	} else if (algId == KMF_ALGID_SHA1WithECDSA ||
735 	    algId == KMF_ALGID_ECDSA) {
736 		create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID);
737 	} else {
738 		/* We only support RSA and DSA keys for now */
739 		rv = KMF_ERR_BAD_ALGORITHM;
740 	}
741 
742 	for (i = 0; i < uNumKeyParts; i++) {
743 		if (KeyParts[i].Data != NULL)
744 			free(KeyParts[i].Data);
745 	}
746 
747 	if (rv != KMF_OK && ID->Data != NULL) {
748 		free(ID->Data);
749 		ID->Data = NULL;
750 		ID->Length = 0;
751 	}
752 
753 	return (rv);
754 }
755 
756 /*
757  * For PKCS1 encoding (necessary for RSA signatures), we
758  * must prepend the following prefixes before computing
759  * the digest.
760  */
761 static uchar_t SHA1_DER_PREFIX[] = {
762 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
763 	0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
764 };
765 static uchar_t MD5_DER_PREFIX[] = {
766 	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
767 	0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
768 	0x04, 0x10
769 };
770 static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d,
771     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
772     0x00, 0x04, 0x20};
773 
774 static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d,
775     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
776     0x00, 0x04, 0x30};
777 
778 static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d,
779     0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
780     0x00, 0x04, 0x40};
781 
782 #define	MAX_SHA2_DIGEST_LENGTH 64
783 /*
784  * Compute hashes using metaslot (or softtoken).
785  * Not all hardware tokens support the combined HASH + RSA/EC
786  * Signing operations so it is safer to separate the hashing
787  * from the signing.  This function generates a hash using a
788  * separate session.  The resulting digest can be signed later.
789  */
790 KMF_RETURN
PKCS_DigestData(KMF_HANDLE_T handle,CK_SESSION_HANDLE hSession,CK_MECHANISM_TYPE mechtype,KMF_DATA * tobesigned,KMF_DATA * output,boolean_t pkcs1_encoding)791 PKCS_DigestData(KMF_HANDLE_T handle,
792     CK_SESSION_HANDLE hSession,
793     CK_MECHANISM_TYPE mechtype,
794     KMF_DATA *tobesigned, KMF_DATA *output,
795     boolean_t pkcs1_encoding)
796 {
797 	KMF_RETURN	rv = KMF_OK;
798 	CK_RV		ckrv;
799 	CK_MECHANISM	mechanism;
800 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
801 	CK_BYTE		outbuf[MAX_SHA2_DIGEST_LENGTH +
802 	    sizeof (SHA512_DER_PREFIX)];
803 	CK_ULONG	outlen = sizeof (outbuf);
804 
805 	mechanism.mechanism = mechtype;
806 	mechanism.pParameter = NULL;
807 	mechanism.ulParameterLen = 0;
808 
809 	ckrv = C_DigestInit(hSession, &mechanism);
810 	if (ckrv != CKR_OK) {
811 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
812 		kmfh->lasterr.errcode = ckrv;
813 		rv = KMF_ERR_INTERNAL;
814 		goto end;
815 	}
816 
817 	ckrv = C_Digest(hSession, tobesigned->Data,
818 	    tobesigned->Length, outbuf, &outlen);
819 	if (ckrv != CKR_OK) {
820 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
821 		kmfh->lasterr.errcode = ckrv;
822 		rv = KMF_ERR_INTERNAL;
823 	}
824 
825 	if (pkcs1_encoding) {
826 		uchar_t *pfx;
827 		int pfxlen;
828 		switch (mechtype) {
829 			case CKM_MD5:
830 				pfx = MD5_DER_PREFIX;
831 				pfxlen = sizeof (MD5_DER_PREFIX);
832 				break;
833 			case CKM_SHA_1:
834 				pfx = SHA1_DER_PREFIX;
835 				pfxlen = sizeof (SHA1_DER_PREFIX);
836 				break;
837 			case CKM_SHA256:
838 				pfx = SHA256_DER_PREFIX;
839 				pfxlen = sizeof (SHA256_DER_PREFIX);
840 				break;
841 			case CKM_SHA384:
842 				pfx = SHA384_DER_PREFIX;
843 				pfxlen = sizeof (SHA384_DER_PREFIX);
844 				break;
845 			case CKM_SHA512:
846 				pfx = SHA512_DER_PREFIX;
847 				pfxlen = sizeof (SHA512_DER_PREFIX);
848 				break;
849 			default:
850 				rv = KMF_ERR_BAD_ALGORITHM;
851 				goto end;
852 		}
853 		(void) memcpy(output->Data, pfx, pfxlen);
854 		(void) memcpy(output->Data + pfxlen, outbuf, outlen);
855 		output->Length = outlen + pfxlen;
856 	} else {
857 		(void) memcpy(output->Data, outbuf, outlen);
858 		output->Length = outlen;
859 	}
860 
861 end:
862 	return (rv);
863 }
864