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
19typedef 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
28static const ALG_INFO alg_info_map[] = {
29	{ KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, 0},
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
60KMF_RETURN
61get_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
86KMF_RETURN
87kmf_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
139out:
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 */
157static int
158PKCS_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 */
181static KMF_RETURN
182PKCS_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
335cleanup:
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 */
358static KMF_RETURN
359PKCS_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 */
431KMF_RETURN
432PKCS_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
537cleanup:
538	if (ckKeyHandle != 0)
539		(void) C_DestroyObject(ckSession, ckKeyHandle);
540	(void) C_CloseSession(ckSession);
541	return (rv);
542}
543
544KMF_RETURN
545PKCS_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 = 0;
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
691static void
692create_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
703KMF_RETURN
704GetIDFromSPKI(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 */
761static uchar_t SHA1_DER_PREFIX[] = {
762	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
763	0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
764};
765static 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};
770static 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
774static 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
778static 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 */
790KMF_RETURN
791PKCS_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
861end:
862	return (rv);
863}
864