pkcs11_spi.c revision 3754:79eeec53e95c
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * PKCS11 token KMF Plugin
23 *
24 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30#include <stdio.h> /* debugging only */
31#include <errno.h>
32#include <values.h>
33
34#include <kmfapiP.h>
35#include <ber_der.h>
36#include <algorithm.h>
37
38#include <cryptoutil.h>
39#include <security/cryptoki.h>
40#include <security/pkcs11.h>
41
42#define	SETATTR(t, n, atype, value, size) \
43	t[n].type = atype; \
44	t[n].pValue = (CK_BYTE *)value; \
45	t[n].ulValueLen = (CK_ULONG)size;
46
47#define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; \
48	h->lasterr.errcode = c;
49
50typedef struct _objlist {
51	CK_OBJECT_HANDLE handle;
52	struct _objlist *next;
53} OBJLIST;
54
55static KMF_RETURN
56search_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
57	boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
58
59static CK_RV
60getObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
61
62static KMF_RETURN
63keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
64
65KMF_RETURN
66KMFPK11_ConfigureKeystore(KMF_HANDLE_T, KMF_CONFIG_PARAMS *);
67
68KMF_RETURN
69KMFPK11_FindCert(KMF_HANDLE_T,
70	KMF_FINDCERT_PARAMS *,
71	KMF_X509_DER_CERT *,
72	uint32_t *);
73
74void
75KMFPK11_FreeKMFCert(KMF_HANDLE_T,
76	KMF_X509_DER_CERT *kmf_cert);
77
78KMF_RETURN
79KMFPK11_StoreCert(KMF_HANDLE_T, KMF_STORECERT_PARAMS *, KMF_DATA *);
80
81KMF_RETURN
82KMFPK11_ImportCert(KMF_HANDLE_T, KMF_IMPORTCERT_PARAMS *);
83
84KMF_RETURN
85KMFPK11_DeleteCert(KMF_HANDLE_T, KMF_DELETECERT_PARAMS *);
86
87KMF_RETURN
88KMFPK11_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
89	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
90
91KMF_RETURN
92KMFPK11_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
93	KMF_KEY_HANDLE *, boolean_t);
94
95KMF_RETURN
96KMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
97
98KMF_RETURN
99KMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
100	KMF_DATA *, KMF_DATA *);
101
102KMF_RETURN
103KMFPK11_GetErrorString(KMF_HANDLE_T, char **);
104
105KMF_RETURN
106KMFPK11_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
107	KMF_KEY_HANDLE *, KMF_KEY_ALG);
108
109KMF_RETURN
110KMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
111	KMF_DATA *, KMF_DATA *);
112
113KMF_RETURN
114KMFPK11_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
115	KMF_KEY_HANDLE *, uint32_t *);
116
117KMF_RETURN
118KMFPK11_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
119	KMF_RAW_KEY_DATA *);
120
121KMF_RETURN
122KMFPK11_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
123	KMF_KEY_HANDLE *);
124
125KMF_RETURN
126KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127
128KMF_RETURN
129KMFPK11_SetTokenPin(KMF_HANDLE_T, KMF_SETPIN_PARAMS *, KMF_CREDENTIAL *);
130
131KMF_RETURN
132KMFPK11_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, KMF_DATA *,
133	KMF_DATA *, KMF_DATA *);
134
135static
136KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
137{
138	1,			/* Version */
139	KMFPK11_ConfigureKeystore,
140	KMFPK11_FindCert,
141	KMFPK11_FreeKMFCert,
142	KMFPK11_StoreCert,
143	KMFPK11_ImportCert,
144	NULL,			/* ImportCRL */
145	KMFPK11_DeleteCert,
146	NULL,			/* DeleteCRL */
147	KMFPK11_CreateKeypair,
148	KMFPK11_FindKey,
149	KMFPK11_EncodePubKeyData,
150	KMFPK11_SignData,
151	KMFPK11_DeleteKey,
152	NULL,			/* ListCRL */
153	NULL,			/* FindCRL */
154	NULL,			/* FindCertInCRL */
155	KMFPK11_GetErrorString,
156	KMFPK11_GetPrikeyByCert,
157	KMFPK11_DecryptData,
158	NULL,			/* ExportP12 */
159	KMFPK11_StorePrivateKey,
160	KMFPK11_CreateSymKey,
161	KMFPK11_GetSymKeyValue,
162	KMFPK11_SetTokenPin,
163	KMFPK11_VerifyDataWithCert,
164	NULL			/* Finalize */
165};
166
167KMF_PLUGIN_FUNCLIST *
168KMF_Plugin_Initialize()
169{
170	return (&pk11token_plugin_table);
171}
172
173KMF_RETURN
174KMFPK11_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
175{
176	KMF_RETURN rv = KMF_OK;
177
178	if (params == NULL || params->pkcs11config.label == NULL)
179		return (KMF_ERR_BAD_PARAMETER);
180
181	rv = KMF_SelectToken(handle, params->pkcs11config.label,
182	    params->pkcs11config.readonly);
183
184	return (rv);
185}
186
187static KMF_RETURN
188pk11_authenticate(KMF_HANDLE_T handle,
189	KMF_CREDENTIAL *cred)
190{
191
192	CK_RV ck_rv = CKR_OK;
193	CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
194
195	if (hSession == NULL)
196		return (KMF_ERR_NO_TOKEN_SELECTED);
197
198	if (cred == NULL || cred->cred == NULL || cred->credlen == 0) {
199		return (KMF_ERR_BAD_PARAMETER);
200	}
201
202	if ((ck_rv = C_Login(hSession, CKU_USER,
203		(uchar_t *)cred->cred, cred->credlen)) != CKR_OK) {
204		if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
205			handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
206			handle->lasterr.errcode = ck_rv;
207			return (KMF_ERR_AUTH_FAILED);
208		}
209	}
210
211	return (KMF_OK);
212}
213
214static KMF_RETURN
215PK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
216		KMF_X509_DER_CERT *kmfcert)
217{
218	KMF_RETURN rv = 0;
219	CK_RV ckrv = CKR_OK;
220
221	CK_CERTIFICATE_TYPE cktype;
222	CK_OBJECT_CLASS	class;
223	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
224	CK_BYTE *subject = NULL, *value = NULL;
225	char *label = NULL;
226	CK_ATTRIBUTE templ[10];
227
228	(void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
229	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
230
231	/*  Is this a certificate object ? */
232	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
233	if (ckrv != CKR_OK || class != CKO_CERTIFICATE)  {
234		SET_ERROR(kmfh, ckrv);
235		return (KMF_ERR_INTERNAL);
236	}
237
238	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
239	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
240
241	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
242		SET_ERROR(kmfh, ckrv);
243		return (ckrv);
244	} else {
245		int i = 0;
246		/* What attributes are available and how big are they? */
247		subject_len = issuer_len = serno_len = id_len = value_len = 0;
248
249		SETATTR(templ, i, CKA_SUBJECT,	NULL, subject_len);
250		i++;
251		SETATTR(templ, i, CKA_ISSUER,	NULL, issuer_len);
252		i++;
253		SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
254		i++;
255		SETATTR(templ, i, CKA_ID, NULL, id_len);
256		i++;
257		SETATTR(templ, i, CKA_VALUE, NULL, value_len);
258		i++;
259
260		/*
261		 * Query the object with NULL values in the pValue spot
262		 * so we know how much space to allocate for each field.
263		 */
264		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
265		if (ckrv != CKR_OK)  {
266			SET_ERROR(kmfh, ckrv);
267			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
268		}
269
270		subject_len	= templ[0].ulValueLen;
271		issuer_len	= templ[1].ulValueLen;
272		serno_len	= templ[2].ulValueLen;
273		id_len		= templ[3].ulValueLen;
274		value_len	= templ[4].ulValueLen;
275
276		/*
277		 * For PKCS#11 CKC_X_509 certificate objects,
278		 * the following attributes must be defined.
279		 * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
280		 * CKA_VALUE.
281		 */
282		if (subject_len == 0 || issuer_len == 0 ||
283		    serno_len == 0 || value_len == 0) {
284			return (KMF_ERR_INTERNAL);
285		}
286
287		/* Only fetch the value field if we are saving the data */
288		if (kmfcert != NULL) {
289			int i = 0;
290			value = malloc(value_len);
291			if (value == NULL) {
292				rv = KMF_ERR_MEMORY;
293				goto errout;
294			}
295
296			SETATTR(templ, i, CKA_VALUE, value, value_len);
297			i++;
298
299			/* re-query the object with room for the value attr */
300			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
301				templ, i);
302
303			if (ckrv != CKR_OK)  {
304				SET_ERROR(kmfh, ckrv);
305				rv = KMF_ERR_INTERNAL;
306				goto errout;
307			}
308
309			kmfcert->certificate.Data = value;
310			kmfcert->certificate.Length = value_len;
311			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
312			kmfcert->kmf_private.keystore_type =
313				KMF_KEYSTORE_PK11TOKEN;
314
315			ckrv = getObjectLabel(kmfh, hObj, &label);
316			if (ckrv == CKR_OK && label != NULL) {
317				kmfcert->kmf_private.label = (char *)label;
318			}
319
320			rv = KMF_OK;
321		}
322	}
323
324errout:
325	if (rv != KMF_OK) {
326		if (subject)
327			free(subject);
328		if (value)
329			free(value);
330
331		if (kmfcert) {
332			kmfcert->certificate.Data = NULL;
333			kmfcert->certificate.Length = 0;
334		}
335	}
336	return (rv);
337}
338
339static void
340free_objlist(OBJLIST *head)
341{
342	OBJLIST *temp = head;
343
344	while (temp != NULL) {
345		head = head->next;
346		free(temp);
347		temp = head;
348	}
349}
350
351/*
352 * The caller should make sure that the templ->pValue is NULL since
353 * it will be overwritten below.
354 */
355static KMF_RETURN
356get_attr(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
357	CK_ATTRIBUTE *templ)
358{
359	CK_RV rv;
360
361	rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
362	if (rv != CKR_OK) {
363		SET_ERROR(kmfh, rv);
364		return (KMF_ERR_INTERNAL);
365	}
366
367	if (templ->ulValueLen > 0) {
368		templ->pValue = malloc(templ->ulValueLen);
369		if (templ->pValue == NULL)
370			return (KMF_ERR_MEMORY);
371
372		rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
373		if (rv != CKR_OK) {
374			SET_ERROR(kmfh, rv);
375			return (KMF_ERR_INTERNAL);
376		}
377	}
378
379	return (KMF_OK);
380}
381
382/*
383 * Match a certificate with an issuer and/or subject name.
384 * This is tricky because we cannot reliably compare DER encodings
385 * because RDNs may have their AV-pairs in different orders even
386 * if the values are the same.  You must compare individual
387 * AV pairs for the RDNs.
388 *
389 * RETURN: 0 for a match, non-zero for a non-match.
390 */
391static KMF_RETURN
392matchcert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
393	KMF_X509_NAME *issuer, KMF_X509_NAME *subject)
394{
395	KMF_RETURN rv = KMF_OK;
396	CK_ATTRIBUTE certattr;
397	KMF_DATA name;
398	KMF_X509_NAME dn;
399
400	if (issuer->numberOfRDNs > 0) {
401		certattr.type = CKA_ISSUER;
402		certattr.pValue = NULL;
403		certattr.ulValueLen = 0;
404
405		rv = get_attr(kmfh, obj, &certattr);
406
407		if (rv == KMF_OK) {
408			name.Data = certattr.pValue;
409			name.Length = certattr.ulValueLen;
410			rv = DerDecodeName(&name, &dn);
411			if (rv == KMF_OK) {
412				rv = KMF_CompareRDNs(issuer, &dn);
413				KMF_FreeDN(&dn);
414			}
415			free(certattr.pValue);
416		}
417
418		if (rv != KMF_OK)
419			return (rv);
420	}
421	if (subject->numberOfRDNs > 0) {
422		certattr.type = CKA_SUBJECT;
423		certattr.pValue = NULL;
424		certattr.ulValueLen = 0;
425
426		rv = get_attr(kmfh, obj, &certattr);
427
428		if (rv == KMF_OK) {
429			name.Data = certattr.pValue;
430			name.Length = certattr.ulValueLen;
431			rv = DerDecodeName(&name, &dn);
432			if (rv == KMF_OK) {
433				rv = KMF_CompareRDNs(subject, &dn);
434				KMF_FreeDN(&dn);
435			}
436			free(certattr.pValue);
437		}
438	}
439
440	return (rv);
441}
442
443/*
444 * delete "curr" node from the "newlist".
445 */
446static void
447pk11_delete_obj_from_list(OBJLIST **newlist,
448	OBJLIST **prev, OBJLIST **curr)
449{
450
451	if (*curr == *newlist) {
452		/* first node in the list */
453		*newlist = (*curr)->next;
454		*prev = (*curr)->next;
455		free(*curr);
456		*curr = *newlist;
457	} else {
458		(*prev)->next = (*curr)->next;
459		free(*curr);
460		*curr = (*prev)->next;
461	}
462}
463
464/*
465 * prepare_object_search
466 *
467 * Because this code is shared by the FindCert and
468 * DeleteCert functions, put it in a separate routine
469 * to save some work and make code easier to debug and
470 * read.
471 */
472static KMF_RETURN
473search_certs(KMF_HANDLE_T handle,
474	char *label, char *issuer, char *subject, KMF_BIGINT *serial,
475	boolean_t private, KMF_CERT_VALIDITY validity,
476	OBJLIST **objlist, uint32_t *numobj)
477{
478	KMF_RETURN rv = KMF_OK;
479	CK_RV ckrv = CKR_OK;
480	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
481	CK_ATTRIBUTE templ[10];
482	CK_BBOOL true = TRUE;
483	CK_OBJECT_CLASS	oclass = CKO_CERTIFICATE;
484	CK_CERTIFICATE_TYPE ctype = CKC_X_509;
485	KMF_X509_NAME subjectDN, issuerDN;
486	int i;
487	OBJLIST *newlist, *tail;
488	CK_ULONG num = 0;
489	uint32_t num_ok_certs = 0; /* number of non-expired or expired certs */
490
491	(void) memset(&templ, 0, 10 * sizeof (CK_ATTRIBUTE));
492	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
493	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
494	i = 0;
495	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
496	SETATTR(templ, i, CKA_CLASS, &oclass, sizeof (oclass)); i++;
497	SETATTR(templ, i, CKA_CERTIFICATE_TYPE, &ctype,
498		sizeof (ctype)); i++;
499
500	if (label != NULL && strlen(label)) {
501		SETATTR(templ, i, CKA_LABEL, label, strlen(label));
502		i++;
503	}
504	if (private) {
505		SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true)); i++;
506	}
507
508	if (issuer != NULL && strlen(issuer)) {
509		if ((rv = KMF_DNParser(issuer, &issuerDN)) != KMF_OK)
510			return (rv);
511	}
512	if (subject != NULL && strlen(subject)) {
513		if ((rv = KMF_DNParser(subject, &subjectDN)) != KMF_OK)
514			return (rv);
515	}
516
517	if (serial != NULL && serial->val != NULL && serial->len > 0) {
518		SETATTR(templ, i, CKA_SERIAL_NUMBER,
519			serial->val, serial->len);
520		i++;
521	}
522
523	(*numobj) = 0;
524	*objlist = NULL;
525	newlist = NULL;
526
527	ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, i);
528	if (ckrv != CKR_OK)
529		goto cleanup;
530
531	tail = newlist = NULL;
532	while (ckrv == CKR_OK) {
533		CK_OBJECT_HANDLE tObj;
534		ckrv = C_FindObjects(kmfh->pk11handle, &tObj, 1, &num);
535		if (ckrv != CKR_OK || num == 0)
536			break;
537
538		/*
539		 * 'matchcert' returns 0 if subject/issuer match
540		 *
541		 * If no match, move on to the next one
542		 */
543		if (matchcert(kmfh, tObj, &issuerDN, &subjectDN))
544			continue;
545
546		if (newlist == NULL) {
547			newlist = malloc(sizeof (OBJLIST));
548			if (newlist == NULL) {
549				rv = KMF_ERR_MEMORY;
550				break;
551			}
552			newlist->handle = tObj;
553			newlist->next = NULL;
554			tail = newlist;
555		} else {
556			tail->next = malloc(sizeof (OBJLIST));
557			if (tail->next != NULL) {
558				tail = tail->next;
559			} else {
560				rv = KMF_ERR_MEMORY;
561				break;
562			}
563			tail->handle = tObj;
564			tail->next = NULL;
565		}
566		(*numobj)++;
567	}
568	ckrv = C_FindObjectsFinal(kmfh->pk11handle);
569
570cleanup:
571	if (ckrv != CKR_OK) {
572		SET_ERROR(kmfh, ckrv);
573		rv = KMF_ERR_INTERNAL;
574		if (newlist != NULL) {
575			free_objlist(newlist);
576			*numobj = 0;
577			newlist = NULL;
578		}
579	} else {
580		if (validity == KMF_ALL_CERTS) {
581			*objlist = newlist;
582		} else {
583			OBJLIST *node, *prev;
584			KMF_X509_DER_CERT  tmp_kmf_cert;
585			uint32_t i = 0;
586
587			node = prev = newlist;
588			/*
589			 * Now check to see if any found certificate is expired
590			 * or valid.
591			 */
592			while (node != NULL && i < (*numobj)) {
593				(void) memset(&tmp_kmf_cert, 0,
594				    sizeof (KMF_X509_DER_CERT));
595				rv = PK11Cert2KMFCert(kmfh, node->handle,
596				    &tmp_kmf_cert);
597				if (rv != KMF_OK) {
598					goto cleanup1;
599				}
600
601				rv = KMF_CheckCertDate(handle,
602				    &tmp_kmf_cert.certificate);
603
604				if (validity == KMF_NONEXPIRED_CERTS) {
605					if (rv == KMF_OK)  {
606						num_ok_certs++;
607						prev = node;
608						node = node->next;
609					} else if (rv ==
610					    KMF_ERR_VALIDITY_PERIOD) {
611						/*
612						 * expired - remove it from list
613						 */
614						pk11_delete_obj_from_list(
615						    &newlist, &prev, &node);
616					} else {
617						goto cleanup1;
618					}
619				}
620
621				if (validity == KMF_EXPIRED_CERTS) {
622					if (rv == KMF_ERR_VALIDITY_PERIOD)  {
623						num_ok_certs++;
624						prev = node;
625						node = node->next;
626						rv = KMF_OK;
627					} else if (rv == KMF_OK) {
628						/*
629						 * valid - remove it from list
630						 */
631						pk11_delete_obj_from_list(
632						    &newlist, &prev, &node);
633					} else {
634						goto cleanup1;
635					}
636				}
637				i++;
638				KMF_FreeKMFCert(handle, &tmp_kmf_cert);
639			}
640			*numobj = num_ok_certs;
641			*objlist = newlist;
642		}
643	}
644
645cleanup1:
646	if (rv != KMF_OK && newlist != NULL) {
647		free_objlist(newlist);
648		*numobj = 0;
649		*objlist = NULL;
650	}
651
652	if (issuer != NULL)
653		KMF_FreeDN(&issuerDN);
654
655	if (subject != NULL)
656		KMF_FreeDN(&subjectDN);
657
658	return (rv);
659}
660
661/*
662 * The caller may pass a NULL value for kmf_cert below and the function will
663 * just return the number of certs found (in num_certs).
664 */
665KMF_RETURN
666KMFPK11_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *params,
667	KMF_X509_DER_CERT *kmf_cert,
668	uint32_t *num_certs)
669{
670	KMF_RETURN rv = 0;
671	uint32_t want_certs;
672	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
673	OBJLIST *objlist = NULL;
674
675	if (!kmfh)
676		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
677
678	if (kmfh->pk11handle == CK_INVALID_HANDLE)
679		return (KMF_ERR_NO_TOKEN_SELECTED);
680
681	if (params == NULL || num_certs == NULL)
682		return (KMF_ERR_BAD_PARAMETER);
683
684	if (*num_certs > 0)
685		want_certs = *num_certs;
686	else
687		want_certs = MAXINT; /* count them all */
688
689	*num_certs = 0;
690
691	rv = search_certs(handle,
692		params->certLabel, params->issuer,
693		params->subject, params->serial,
694		params->pkcs11parms.private,
695		params->find_cert_validity,
696		&objlist, num_certs);
697
698	if (rv == KMF_OK && objlist != NULL && kmf_cert != NULL) {
699		OBJLIST *node = objlist;
700		int i = 0;
701		while (node != NULL && i < want_certs) {
702			rv = PK11Cert2KMFCert(kmfh, node->handle,
703				&kmf_cert[i]);
704			i++;
705			node = node->next;
706		}
707	}
708
709	if (objlist != NULL)
710		free_objlist(objlist);
711
712	if (*num_certs == 0)
713		rv = KMF_ERR_CERT_NOT_FOUND;
714
715	return (rv);
716}
717
718/*ARGSUSED*/
719void
720KMFPK11_FreeKMFCert(KMF_HANDLE_T handle,
721	KMF_X509_DER_CERT *kmf_cert)
722{
723	if (kmf_cert != NULL && kmf_cert->certificate.Data != NULL) {
724		free(kmf_cert->certificate.Data);
725		kmf_cert->certificate.Data = NULL;
726		kmf_cert->certificate.Length = 0;
727
728		if (kmf_cert->kmf_private.label != NULL) {
729			free(kmf_cert->kmf_private.label);
730			kmf_cert->kmf_private.label = NULL;
731		}
732	}
733}
734
735KMF_RETURN
736KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
737		KMF_DATA *eData)
738{
739	KMF_RETURN ret = KMF_OK;
740	CK_RV rv;
741	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
742	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
743	CK_KEY_TYPE ckKeyType;
744	KMF_DATA Modulus, Exponent, Prime, Subprime, Base, Value;
745	KMF_OID *Algorithm;
746	BerElement *asn1 = NULL;
747	BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
748	KMF_X509_SPKI spki;
749
750	CK_ATTRIBUTE rsaTemplate[4];
751	CK_ATTRIBUTE dsaTemplate[6];
752
753	if (!kmfh)
754		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
755
756	if (kmfh->pk11handle == CK_INVALID_HANDLE)
757		return (KMF_ERR_NO_TOKEN_SELECTED);
758
759	if (pKey == NULL || pKey->keyp == CK_INVALID_HANDLE)
760		return (KMF_ERR_BAD_PARAMETER);
761
762	(void) memset(&Modulus, 0, sizeof (Modulus));
763	(void) memset(&Exponent, 0, sizeof (Exponent));
764	(void) memset(&Prime, 0, sizeof (Prime));
765	(void) memset(&Subprime, 0, sizeof (Subprime));
766	(void) memset(&Base, 0, sizeof (Base));
767	(void) memset(&Value, 0, sizeof (Value));
768
769	SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
770	SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
771	SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, &Modulus.Length);
772	SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, Exponent.Data,
773		&Exponent.Length);
774
775	SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
776	SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
777	SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, &Prime.Length);
778	SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, &Subprime.Length);
779	SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, &Base.Length);
780	SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, &Value.Length);
781
782	switch (pKey->keyalg) {
783		case KMF_RSA:
784			/* Get the length of the fields */
785			rv = C_GetAttributeValue(kmfh->pk11handle,
786				(CK_OBJECT_HANDLE)pKey->keyp,
787				rsaTemplate, 4);
788			if (rv != CKR_OK) {
789				SET_ERROR(kmfh, rv);
790				return (KMF_ERR_BAD_PARAMETER);
791			}
792
793			Modulus.Length = rsaTemplate[2].ulValueLen;
794			Modulus.Data = malloc(Modulus.Length);
795			if (Modulus.Data == NULL)
796				return (KMF_ERR_MEMORY);
797
798			Exponent.Length = rsaTemplate[3].ulValueLen;
799			Exponent.Data = malloc(Exponent.Length);
800			if (Exponent.Data == NULL) {
801				free(Modulus.Data);
802				return (KMF_ERR_MEMORY);
803			}
804
805			SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
806					Modulus.Length);
807			SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
808					Exponent.Data, Exponent.Length);
809			/* Now get the values */
810			rv = C_GetAttributeValue(kmfh->pk11handle,
811				(CK_OBJECT_HANDLE)pKey->keyp,
812				rsaTemplate, 4);
813			if (rv != CKR_OK) {
814				SET_ERROR(kmfh, rv);
815				free(Modulus.Data);
816				free(Exponent.Data);
817				return (KMF_ERR_BAD_PARAMETER);
818			}
819
820			/*
821			 * This is the KEY algorithm, not the
822			 * signature algorithm.
823			 */
824			Algorithm = X509_AlgIdToAlgorithmOid(KMF_ALGID_RSA);
825			if (Algorithm != NULL) {
826
827				/* Encode the RSA Key Data */
828				if ((asn1 = kmfder_alloc()) == NULL) {
829					free(Modulus.Data);
830					free(Exponent.Data);
831					return (KMF_ERR_MEMORY);
832				}
833				if (kmfber_printf(asn1, "{II}",
834					Modulus.Data, Modulus.Length,
835					Exponent.Data, Exponent.Length) == -1) {
836					kmfber_free(asn1, 1);
837					free(Modulus.Data);
838					free(Exponent.Data);
839					return (KMF_ERR_ENCODING);
840				}
841				if (kmfber_flatten(asn1, &EncodedKey) == -1) {
842					kmfber_free(asn1, 1);
843					free(Modulus.Data);
844					free(Exponent.Data);
845					return (KMF_ERR_ENCODING);
846				}
847				kmfber_free(asn1, 1);
848			}
849
850			free(Exponent.Data);
851			free(Modulus.Data);
852
853			break;
854		case KMF_DSA:
855			/* Get the length of the fields */
856			rv = C_GetAttributeValue(kmfh->pk11handle,
857				(CK_OBJECT_HANDLE)pKey->keyp,
858				dsaTemplate, 6);
859			if (rv != CKR_OK) {
860				SET_ERROR(kmfh, rv);
861				return (KMF_ERR_BAD_PARAMETER);
862			}
863			Prime.Length = dsaTemplate[2].ulValueLen;
864			Prime.Data = malloc(Prime.Length);
865			if (Prime.Data == NULL) {
866				return (KMF_ERR_MEMORY);
867			}
868
869			Subprime.Length = dsaTemplate[3].ulValueLen;
870			Subprime.Data = malloc(Subprime.Length);
871			if (Subprime.Data == NULL) {
872				free(Prime.Data);
873				return (KMF_ERR_MEMORY);
874			}
875
876			Base.Length = dsaTemplate[4].ulValueLen;
877			Base.Data = malloc(Base.Length);
878			if (Base.Data == NULL) {
879				free(Prime.Data);
880				free(Subprime.Data);
881				return (KMF_ERR_MEMORY);
882			}
883
884			Value.Length = dsaTemplate[5].ulValueLen;
885			Value.Data = malloc(Value.Length);
886			if (Value.Data == NULL) {
887				free(Prime.Data);
888				free(Subprime.Data);
889				free(Base.Data);
890				return (KMF_ERR_MEMORY);
891			}
892			SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
893					Prime.Length);
894			SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
895					Subprime.Length);
896			SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
897					Base.Length);
898			SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
899					Value.Length);
900
901			/* Now get the values */
902			rv = C_GetAttributeValue(kmfh->pk11handle,
903				(CK_OBJECT_HANDLE)pKey->keyp,
904				dsaTemplate, 6);
905			if (rv != CKR_OK) {
906				free(Prime.Data);
907				free(Subprime.Data);
908				free(Base.Data);
909				free(Value.Data);
910				SET_ERROR(kmfh, rv);
911				return (KMF_ERR_BAD_PARAMETER);
912			}
913			/*
914			 * This is the KEY algorithm, not the
915			 * signature algorithm.
916			 */
917			Algorithm =
918			    X509_AlgIdToAlgorithmOid(KMF_ALGID_DSA);
919
920			/* Encode the DSA Algorithm Parameters */
921			if ((asn1 = kmfder_alloc()) == NULL) {
922				free(Prime.Data);
923				free(Subprime.Data);
924				free(Base.Data);
925				free(Value.Data);
926				return (KMF_ERR_MEMORY);
927			}
928
929			if (kmfber_printf(asn1, "{III}",
930				Prime.Data, Prime.Length,
931				Subprime.Data, Subprime.Length,
932				Base.Data, Base.Length) == -1) {
933
934				kmfber_free(asn1, 1);
935				free(Prime.Data);
936				free(Subprime.Data);
937				free(Base.Data);
938				free(Value.Data);
939				return (KMF_ERR_ENCODING);
940			}
941			if (kmfber_flatten(asn1, &PubKeyParams) == -1) {
942				kmfber_free(asn1, 1);
943				free(Prime.Data);
944				free(Subprime.Data);
945				free(Base.Data);
946				free(Value.Data);
947				return (KMF_ERR_ENCODING);
948			}
949			kmfber_free(asn1, 1);
950			free(Prime.Data);
951			free(Subprime.Data);
952			free(Base.Data);
953
954			/* Encode the DSA Key Value */
955			if ((asn1 = kmfder_alloc()) == NULL) {
956				free(Value.Data);
957				return (KMF_ERR_MEMORY);
958			}
959
960			if (kmfber_printf(asn1, "I",
961				Value.Data, Value.Length) == -1) {
962				kmfber_free(asn1, 1);
963				free(Value.Data);
964				return (KMF_ERR_ENCODING);
965			}
966			if (kmfber_flatten(asn1, &EncodedKey) == -1) {
967				kmfber_free(asn1, 1);
968				free(Value.Data);
969				return (KMF_ERR_ENCODING);
970			}
971			kmfber_free(asn1, 1);
972			free(Value.Data);
973			break;
974		default:
975			return (KMF_ERR_BAD_PARAMETER);
976	}
977
978	/* Now, build an SPKI structure for the final encoding step */
979	spki.algorithm.algorithm = *Algorithm;
980	if (PubKeyParams != NULL) {
981		spki.algorithm.parameters.Data =
982			(uchar_t *)PubKeyParams->bv_val;
983		spki.algorithm.parameters.Length = PubKeyParams->bv_len;
984	} else {
985		spki.algorithm.parameters.Data = NULL;
986		spki.algorithm.parameters.Length = 0;
987	}
988
989	if (EncodedKey != NULL) {
990		spki.subjectPublicKey.Data = (uchar_t *)EncodedKey->bv_val;
991		spki.subjectPublicKey.Length = EncodedKey->bv_len;
992	} else {
993		spki.subjectPublicKey.Data = NULL;
994		spki.subjectPublicKey.Length = 0;
995	}
996
997	/* Finally, encode the entire SPKI record */
998	ret = DerEncodeSPKI(&spki, eData);
999
1000cleanup:
1001	if (EncodedKey) {
1002		free(EncodedKey->bv_val);
1003		free(EncodedKey);
1004	}
1005
1006	if (PubKeyParams) {
1007		free(PubKeyParams->bv_val);
1008		free(PubKeyParams);
1009	}
1010
1011	return (ret);
1012}
1013
1014
1015static KMF_RETURN
1016CreateCertObject(KMF_HANDLE_T handle, char *label, KMF_DATA *pcert)
1017{
1018	KMF_RETURN rv = 0;
1019	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1020
1021	KMF_X509_CERTIFICATE *signed_cert_ptr = NULL;
1022	KMF_DATA data;
1023	KMF_DATA Id;
1024
1025	CK_RV ckrv;
1026	CK_ULONG subject_len, issuer_len, serno_len;
1027	CK_BYTE *subject, *issuer, *serial, nullserno;
1028	CK_BBOOL true = TRUE;
1029	CK_CERTIFICATE_TYPE certtype = CKC_X_509;
1030	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1031	CK_ATTRIBUTE x509templ[11];
1032	CK_OBJECT_HANDLE hCert = NULL;
1033	int i;
1034
1035	if (!kmfh)
1036		return (KMF_ERR_INTERNAL); /* should not happen */
1037
1038	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1039		return (KMF_ERR_INTERNAL); /* should not happen */
1040
1041	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1042		return (KMF_ERR_INTERNAL);  /* should not happen */
1043
1044	/*
1045	 * The data *must* be a DER encoded X.509 certificate.
1046	 * Convert it to a CSSM cert and then parse the fields so
1047	 * the PKCS#11 attributes can be filled in correctly.
1048	 */
1049	rv = DerDecodeSignedCertificate((const KMF_DATA *)pcert,
1050		&signed_cert_ptr);
1051	if (rv != KMF_OK) {
1052		return (KMF_ERR_ENCODING);
1053	}
1054
1055	/*
1056	 * Encode fields into PKCS#11 attributes.
1057	 */
1058
1059	/* Get the subject name */
1060	rv = DerEncodeName(&signed_cert_ptr->certificate.subject, &data);
1061	if (rv == KMF_OK) {
1062		subject = data.Data;
1063		subject_len = data.Length;
1064	} else {
1065		rv = KMF_ERR_ENCODING;
1066		goto cleanup;
1067	}
1068
1069	/* Encode the issuer */
1070	rv = DerEncodeName(&signed_cert_ptr->certificate.issuer, &data);
1071	if (rv == KMF_OK) {
1072		issuer = data.Data;
1073		issuer_len = data.Length;
1074	} else {
1075		rv = KMF_ERR_ENCODING;
1076		goto cleanup;
1077	}
1078
1079	/* Encode serial number */
1080	if (signed_cert_ptr->certificate.serialNumber.len > 0 &&
1081	    signed_cert_ptr->certificate.serialNumber.val != NULL) {
1082		serial = signed_cert_ptr->certificate.serialNumber.val;
1083		serno_len = signed_cert_ptr->certificate.serialNumber.len;
1084	} else {
1085		/*
1086		 * RFC3280 says to gracefully handle certs with serial numbers
1087		 * of 0.
1088		 */
1089		nullserno = '\0';
1090		serial  = &nullserno;
1091		serno_len = 1;
1092	}
1093
1094	/* Generate an ID from the SPKI data */
1095	rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
1096			&Id);
1097
1098	if (rv != KMF_OK) {
1099		SET_ERROR(kmfh, rv);
1100		goto cleanup;
1101	}
1102
1103	i = 0;
1104	SETATTR(x509templ, i, CKA_CLASS, &certClass,
1105		sizeof (certClass)); i++;
1106	SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
1107		sizeof (certtype)); i++;
1108	SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
1109	SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
1110	SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
1111	SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
1112	SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
1113	SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
1114	if (label != NULL && strlen(label)) {
1115		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));
1116		i++;
1117	}
1118	/*
1119	 * The cert object handle is actually "leaked" here.  If the app
1120	 * really wants to clean up the data space, it will have to call
1121	 * KMF_DeleteCert and specify the softtoken keystore.
1122	 */
1123	ckrv = C_CreateObject(kmfh->pk11handle, x509templ, i, &hCert);
1124	if (ckrv != CKR_OK) {
1125		SET_ERROR(kmfh, rv);
1126		rv = KMF_ERR_INTERNAL;
1127	}
1128	free(subject);
1129	free(issuer);
1130
1131cleanup:
1132	if (Id.Data != NULL)
1133		free(Id.Data);
1134
1135	if (signed_cert_ptr) {
1136		KMF_FreeSignedCert(signed_cert_ptr);
1137		free(signed_cert_ptr);
1138	}
1139	return (rv);
1140}
1141
1142
1143KMF_RETURN
1144KMFPK11_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
1145		KMF_DATA *pcert)
1146{
1147	KMF_RETURN rv = 0;
1148	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1149
1150	if (!kmfh)
1151		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1152
1153	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1154		return (KMF_ERR_NO_TOKEN_SELECTED);
1155
1156	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1157		return (KMF_ERR_BAD_PARAMETER);
1158
1159	rv = CreateCertObject(handle, params->certLabel, pcert);
1160	return (rv);
1161}
1162
1163
1164
1165KMF_RETURN
1166KMFPK11_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *params)
1167{
1168	KMF_RETURN rv = 0;
1169	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1170	KMF_ENCODE_FORMAT format;
1171	KMF_DATA  cert1 = { NULL, 0};
1172	KMF_DATA  cert2 = { NULL, 0};
1173
1174	if (!kmfh)
1175		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1176
1177	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1178		return (KMF_ERR_NO_TOKEN_SELECTED);
1179
1180	if (params == NULL || params->certfile == NULL) {
1181		return (KMF_ERR_BAD_PARAMETER);
1182	}
1183
1184	/*
1185	 * Check if the input cert file is a valid certificate and
1186	 * auto-detect the file format of it.
1187	 */
1188	rv = KMF_IsCertFile(handle, params->certfile, &format);
1189	if (rv != KMF_OK)
1190		return (rv);
1191
1192	/* Read in the CERT file */
1193	rv = KMF_ReadInputFile(handle, params->certfile, &cert1);
1194	if (rv != KMF_OK) {
1195		return (rv);
1196	}
1197
1198	/*
1199	 * If the input certificate is in PEM format, we need to convert
1200	 * it to DER first.
1201	 */
1202	if (format == KMF_FORMAT_PEM) {
1203		int derlen;
1204		rv = KMF_Pem2Der(cert1.Data, cert1.Length,
1205		    &cert2.Data, &derlen);
1206		if (rv != KMF_OK) {
1207			goto out;
1208		}
1209		cert2.Length = (size_t)derlen;
1210	}
1211
1212	rv = CreateCertObject(handle, params->certLabel,
1213	    format == KMF_FORMAT_ASN1 ? &cert1 : &cert2);
1214
1215out:
1216	if (cert1.Data != NULL) {
1217		free(cert1.Data);
1218	}
1219
1220	if (cert2.Data != NULL) {
1221		free(cert2.Data);
1222	}
1223
1224	return (rv);
1225}
1226
1227KMF_RETURN
1228KMFPK11_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
1229{
1230	KMF_RETURN rv = 0;
1231	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1232	OBJLIST *objlist;
1233	uint32_t numObjects = 0;
1234
1235	if (!kmfh)
1236		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1237
1238	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1239		return (KMF_ERR_NO_TOKEN_SELECTED);
1240
1241	if (params == NULL)
1242		return (KMF_ERR_BAD_PARAMETER);
1243
1244	/*
1245	 * Use the same search routine as is used for the FindCert
1246	 * operation.
1247	 */
1248	objlist = NULL;
1249	rv = search_certs(handle,
1250		params->certLabel, params->issuer,
1251		params->subject, params->serial,
1252		params->pkcs11parms.private,
1253		params->find_cert_validity,
1254		&objlist, &numObjects);
1255
1256	if (rv == KMF_OK && objlist != NULL) {
1257		OBJLIST *node = objlist;
1258
1259		while (node != NULL) {
1260			CK_RV ckrv;
1261			ckrv = C_DestroyObject(kmfh->pk11handle,
1262				node->handle);
1263			if (ckrv != CKR_OK) {
1264				SET_ERROR(kmfh, ckrv);
1265				rv = KMF_ERR_INTERNAL;
1266				break;
1267			}
1268			node = node->next;
1269		}
1270		free_objlist(objlist);
1271	}
1272
1273	if (rv == KMF_OK && numObjects == 0)
1274		rv = KMF_ERR_CERT_NOT_FOUND;
1275
1276out:
1277	return (rv);
1278}
1279
1280KMF_RETURN
1281KMFPK11_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
1282	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
1283{
1284	KMF_RETURN rv = KMF_OK;
1285	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1286
1287	CK_RV			ckrv = 0;
1288	CK_OBJECT_HANDLE	pubKey = CK_INVALID_HANDLE;
1289	CK_OBJECT_HANDLE	priKey = CK_INVALID_HANDLE;
1290	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1291
1292	static CK_OBJECT_CLASS	priClass = CKO_PRIVATE_KEY;
1293	static CK_OBJECT_CLASS	pubClass = CKO_PUBLIC_KEY;
1294
1295	static CK_ULONG	rsaKeyType = CKK_RSA;
1296	static CK_ULONG	modulusBits = 1024;
1297	static CK_BYTE	PubExpo[3] = {0x01, 0x00, 0x01};
1298	static CK_BBOOL	true = TRUE;
1299	static CK_BBOOL	ontoken = TRUE;
1300	static CK_BBOOL	false = FALSE;
1301	static CK_ULONG	dsaKeyType = CKK_DSA;
1302
1303	CK_ATTRIBUTE rsaPubKeyTemplate[8];
1304	CK_ATTRIBUTE rsaPriKeyTemplate[6];
1305
1306	static CK_BYTE ckDsaPrime[128] = {
1307	0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
1308	0xcf, 0xdd, 0xf9, 0xae, 0x3e, 0x39, 0x7f, 0x9c,
1309	0xa7, 0x73, 0xc3, 0x00, 0xa3, 0x50, 0x67, 0xc3,
1310	0xab, 0x49, 0x2c, 0xea, 0x59, 0x10, 0xa4, 0xbc,
1311	0x09, 0x94, 0xa9, 0x05, 0x3b, 0x0d, 0x35, 0x3c,
1312	0x55, 0x52, 0x47, 0xf0, 0xe3, 0x72, 0x5b, 0xe8,
1313	0x72, 0xa0, 0x71, 0x1c, 0x23, 0x4f, 0x6d, 0xe8,
1314	0xac, 0xe5, 0x21, 0x1b, 0xc0, 0xd8, 0x42, 0xd3,
1315	0x87, 0xae, 0x83, 0x5e, 0x52, 0x7e, 0x46, 0x09,
1316	0xb5, 0xc7, 0x3d, 0xd6, 0x00, 0xf5, 0xf2, 0x9c,
1317	0x84, 0x30, 0x81, 0x7e, 0x7b, 0x30, 0x5b, 0xd5,
1318	0xab, 0xd0, 0x2f, 0x21, 0xb3, 0xd8, 0xed, 0xdb,
1319	0x97, 0x77, 0xe4, 0x7e, 0x6c, 0xcc, 0xb9, 0x6b,
1320	0xdd, 0xaa, 0x96, 0x04, 0xe7, 0xd4, 0x55, 0x11,
1321	0x53, 0xab, 0xba, 0x95, 0x9a, 0xa2, 0x8c, 0x27,
1322	0xd9, 0xcf, 0xad, 0xf3, 0xcf, 0x3a, 0x0c, 0x4b};
1323
1324	static CK_BYTE ckDsaSubPrime[20] = {
1325	0xa4, 0x5f, 0x2a, 0x27, 0x09, 0x49, 0xb6, 0xfe,
1326	0x73, 0xeb, 0x95, 0x7d, 0x00, 0xf3, 0x42, 0xfc,
1327	0x78, 0x47, 0xb0, 0xd5};
1328
1329	static CK_BYTE ckDsaBase[128] = {
1330	0x5c, 0x57, 0x16, 0x49, 0xef, 0xc8, 0xfb, 0x4b,
1331	0xee, 0x07, 0x45, 0x3b, 0x6a, 0x1d, 0xf3, 0xe5,
1332	0xeb, 0xee, 0xad, 0x11, 0x13, 0xe3, 0x52, 0xe3,
1333	0x0d, 0xc0, 0x21, 0x25, 0xfa, 0xf0, 0x93, 0x1c,
1334	0x53, 0x4d, 0xdc, 0x0d, 0x76, 0xd2, 0xfe, 0xc2,
1335	0xd7, 0x72, 0x64, 0x69, 0x53, 0x3d, 0x33, 0xbd,
1336	0xe1, 0x34, 0xf2, 0x5a, 0x67, 0x83, 0xe0, 0xd3,
1337	0x1c, 0xd6, 0x41, 0x4d, 0x16, 0xe8, 0x6c, 0x5a,
1338	0x07, 0x95, 0x21, 0x9a, 0xa3, 0xc4, 0xb9, 0x05,
1339	0x9d, 0x11, 0xcb, 0xc8, 0xc4, 0x9d, 0x00, 0x1a,
1340	0xf4, 0x85, 0x2a, 0xa9, 0x20, 0x3c, 0xba, 0x67,
1341	0xe5, 0xed, 0x31, 0xb2, 0x11, 0xfb, 0x1f, 0x73,
1342	0xec, 0x61, 0x29, 0xad, 0xc7, 0x68, 0xb2, 0x3f,
1343	0x38, 0xea, 0xd9, 0x87, 0x83, 0x9e, 0x7e, 0x19,
1344	0x18, 0xdd, 0xc2, 0xc3, 0x5b, 0x16, 0x6d, 0xce,
1345	0xcf, 0x88, 0x91, 0x07, 0xe0, 0x2b, 0xa8, 0x54 };
1346
1347	static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
1348	{ CKA_CLASS, &pubClass, sizeof (pubClass) },
1349	{ CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
1350	{ CKA_TOKEN, &ontoken, sizeof (ontoken)},
1351	{ CKA_PRIVATE, &false, sizeof (false)},
1352	{ CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) },
1353	{ CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)},
1354	{ CKA_BASE, &ckDsaBase, sizeof (ckDsaBase) },
1355	{ CKA_VERIFY, &true, sizeof (true) },
1356};
1357
1358#define	NUMBER_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1359					sizeof (CK_ATTRIBUTE))
1360#define	MAX_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1361				    sizeof (CK_ATTRIBUTE))
1362
1363	static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
1364	{CKA_CLASS, &priClass, sizeof (priClass)},
1365	{CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
1366	{CKA_TOKEN, &ontoken, sizeof (ontoken)},
1367	{CKA_PRIVATE, &true, sizeof (true)},
1368	{CKA_SIGN, &true, sizeof (true)},
1369	};
1370
1371	CK_ATTRIBUTE labelattr[1];
1372	CK_ATTRIBUTE idattr[1];
1373	char IDHashData[SHA1_HASH_LENGTH];
1374	KMF_DATA IDInput, IDOutput;
1375
1376#define	NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1377					sizeof (CK_ATTRIBUTE))
1378#define	MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1379				sizeof (CK_ATTRIBUTE))
1380
1381	if (!kmfh)
1382		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1383
1384	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1385		return (KMF_ERR_NO_TOKEN_SELECTED);
1386
1387	if (params == NULL)
1388		return (KMF_ERR_BAD_PARAMETER);
1389
1390	rv = pk11_authenticate(handle, &params->cred);
1391	if (rv != KMF_OK) {
1392		return (rv);
1393	}
1394
1395	if (params->keytype == KMF_RSA) {
1396		CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN,
1397			NULL, 0};
1398		CK_BYTE *modulus;
1399		CK_ULONG modulusLength;
1400		CK_ATTRIBUTE modattr[1];
1401
1402		SETATTR(rsaPubKeyTemplate, 0, CKA_CLASS,
1403			&pubClass, sizeof (pubClass));
1404		SETATTR(rsaPubKeyTemplate, 1, CKA_KEY_TYPE,
1405			&rsaKeyType, sizeof (rsaKeyType));
1406		SETATTR(rsaPubKeyTemplate, 2, CKA_TOKEN,
1407			&false, sizeof (false));
1408		SETATTR(rsaPubKeyTemplate, 3, CKA_PRIVATE,
1409			&false, sizeof (false));
1410		SETATTR(rsaPubKeyTemplate, 4, CKA_MODULUS_BITS,
1411			&modulusBits, sizeof (modulusBits));
1412		if (params->rsa_exponent.len > 0 &&
1413			params->rsa_exponent.val != NULL) {
1414			SETATTR(rsaPubKeyTemplate, 5,
1415				CKA_PUBLIC_EXPONENT,
1416				params->rsa_exponent.val,
1417				params->rsa_exponent.len);
1418		} else {
1419			SETATTR(rsaPubKeyTemplate, 5,
1420				CKA_PUBLIC_EXPONENT, &PubExpo,
1421				sizeof (PubExpo));
1422		}
1423		SETATTR(rsaPubKeyTemplate, 6, CKA_ENCRYPT,
1424			&true, sizeof (true));
1425		SETATTR(rsaPubKeyTemplate, 7, CKA_VERIFY,
1426			&true, sizeof (true));
1427
1428		SETATTR(rsaPriKeyTemplate, 0, CKA_CLASS, &priClass,
1429			sizeof (priClass));
1430		SETATTR(rsaPriKeyTemplate, 1, CKA_KEY_TYPE, &rsaKeyType,
1431			sizeof (rsaKeyType));
1432		SETATTR(rsaPriKeyTemplate, 2, CKA_TOKEN, &ontoken,
1433			sizeof (ontoken));
1434		SETATTR(rsaPriKeyTemplate, 3, CKA_PRIVATE, &true,
1435			sizeof (true));
1436		SETATTR(rsaPriKeyTemplate, 4, CKA_DECRYPT, &true,
1437			sizeof (true));
1438		SETATTR(rsaPriKeyTemplate, 5, CKA_SIGN, &true,
1439			sizeof (true));
1440
1441		SETATTR(modattr, 0, CKA_MODULUS, NULL, &modulusLength);
1442
1443		modulusBits = params->keylength;
1444
1445		pubKey = CK_INVALID_HANDLE;
1446		priKey = CK_INVALID_HANDLE;
1447		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1448			rsaPubKeyTemplate,
1449			(sizeof (rsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1450			rsaPriKeyTemplate,
1451			(sizeof (rsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1452			&pubKey, &priKey);
1453		if (ckrv != CKR_OK) {
1454			SET_ERROR(kmfh, ckrv);
1455			return (KMF_ERR_KEYGEN_FAILED);
1456		}
1457
1458		if (privkey != NULL) {
1459			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1460			privkey->keyalg = KMF_RSA;
1461			privkey->keyclass = KMF_ASYM_PRI;
1462			privkey->keyp = (void *)priKey;
1463		}
1464		if (pubkey != NULL) {
1465			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1466			pubkey->keyalg = KMF_RSA;
1467			pubkey->keyclass = KMF_ASYM_PUB;
1468			pubkey->keyp = (void *)pubKey;
1469		}
1470
1471		/* Get the Modulus field to use as input for creating the ID */
1472		rv = C_GetAttributeValue(kmfh->pk11handle,
1473			(CK_OBJECT_HANDLE)pubKey,
1474			modattr, 1);
1475		if (rv != CKR_OK) {
1476			SET_ERROR(kmfh, ckrv);
1477			return (KMF_ERR_BAD_PARAMETER);
1478		}
1479
1480		modulusLength = modattr[0].ulValueLen;
1481		modulus = malloc(modulusLength);
1482		if (modulus == NULL)
1483			return (KMF_ERR_MEMORY);
1484
1485		modattr[0].pValue = modulus;
1486		rv = C_GetAttributeValue(kmfh->pk11handle,
1487			(CK_OBJECT_HANDLE)pubKey,
1488			modattr, 1);
1489		if (rv != CKR_OK) {
1490			SET_ERROR(kmfh, ckrv);
1491			free(modulus);
1492			return (KMF_ERR_BAD_PARAMETER);
1493		}
1494
1495		IDInput.Data = modulus;
1496		IDInput.Length = modulusLength;
1497
1498	} else if (params->keytype == KMF_DSA) {
1499		CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
1500		CK_BYTE *keyvalue;
1501		CK_ULONG valueLen;
1502		CK_ATTRIBUTE valattr[1];
1503
1504		SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
1505				&ontoken, sizeof (ontoken));
1506		SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen);
1507
1508		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1509			ckDsaPubKeyTemplate,
1510			(sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1511			ckDsaPriKeyTemplate,
1512			(sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1513			&pubKey, &priKey);
1514		if (ckrv != CKR_OK) {
1515			SET_ERROR(kmfh, ckrv);
1516			return (KMF_ERR_KEYGEN_FAILED);
1517		}
1518
1519		if (privkey != NULL) {
1520			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1521			privkey->keyalg = KMF_DSA;
1522			privkey->keyclass = KMF_ASYM_PRI;
1523			privkey->keyp = (void *)priKey;
1524		}
1525		if (pubkey != NULL) {
1526			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1527			pubkey->keyalg = KMF_DSA;
1528			pubkey->keyclass = KMF_ASYM_PUB;
1529			pubkey->keyp = (void *)pubKey;
1530		}
1531		/* Get the Public Value to use as input for creating the ID */
1532		rv = C_GetAttributeValue(hSession,
1533			(CK_OBJECT_HANDLE)pubKey,
1534			valattr, 1);
1535		if (rv != CKR_OK) {
1536			SET_ERROR(kmfh, ckrv);
1537			return (KMF_ERR_BAD_PARAMETER);
1538		}
1539
1540		valueLen = valattr[0].ulValueLen;
1541		keyvalue = malloc(valueLen);
1542		if (keyvalue == NULL)
1543			return (KMF_ERR_MEMORY);
1544
1545		valattr[0].pValue = keyvalue;
1546		rv = C_GetAttributeValue(hSession,
1547			(CK_OBJECT_HANDLE)pubKey,
1548			valattr, 1);
1549		if (rv != CKR_OK) {
1550			SET_ERROR(kmfh, ckrv);
1551			free(keyvalue);
1552			return (KMF_ERR_BAD_PARAMETER);
1553		}
1554
1555		IDInput.Data = keyvalue;
1556		IDInput.Length = valueLen;
1557	} else {
1558		return (KMF_ERR_BAD_PARAMETER);
1559	}
1560
1561	if (params->keylabel != NULL &&
1562		strlen(params->keylabel)) {
1563
1564		SETATTR(labelattr, 0, CKA_LABEL, params->keylabel,
1565			strlen(params->keylabel));
1566
1567		/* Set the CKA_LABEL if one was indicated */
1568		if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1569			labelattr, 1)) != CKR_OK) {
1570			SET_ERROR(kmfh, ckrv);
1571			rv = KMF_ERR_INTERNAL;
1572			goto cleanup;
1573		}
1574		if (pubkey != NULL) {
1575			pubkey->keylabel =
1576				(char *)strdup(params->keylabel);
1577			if (pubkey->keylabel == NULL) {
1578				rv = KMF_ERR_MEMORY;
1579				goto cleanup;
1580			}
1581		}
1582		if ((ckrv = C_SetAttributeValue(hSession, priKey,
1583			labelattr, 1)) != CKR_OK) {
1584			SET_ERROR(kmfh, ckrv);
1585			rv = KMF_ERR_INTERNAL;
1586			goto cleanup;
1587		}
1588		if (privkey != NULL) {
1589			privkey->keylabel =
1590				(char *)strdup(params->keylabel);
1591			if (privkey->keylabel == NULL) {
1592				rv = KMF_ERR_MEMORY;
1593				goto cleanup;
1594			}
1595		}
1596	}
1597
1598	/* Now, assign a CKA_ID value so it can be searched */
1599	/* ID_Input was assigned above in the RSA or DSA keygen section */
1600	IDOutput.Data = (uchar_t *)IDHashData;
1601	IDOutput.Length = sizeof (IDHashData);
1602
1603	rv = DigestData(hSession, &IDInput, &IDOutput);
1604	free(IDInput.Data);
1605
1606	if (rv != CKR_OK) {
1607		SET_ERROR(kmfh, rv);
1608		goto cleanup;
1609	}
1610	SETATTR(idattr, 0, CKA_ID, IDOutput.Data, IDOutput.Length);
1611	if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1612			idattr, 1)) != CKR_OK) {
1613		SET_ERROR(kmfh, ckrv);
1614		rv = KMF_ERR_INTERNAL;
1615		goto cleanup;
1616	}
1617	if ((ckrv = C_SetAttributeValue(hSession, priKey,
1618			idattr, 1)) != CKR_OK) {
1619		SET_ERROR(kmfh, ckrv);
1620		rv = KMF_ERR_INTERNAL;
1621		goto cleanup;
1622	}
1623
1624cleanup:
1625	if (rv != KMF_OK) {
1626		if (pubKey != CK_INVALID_HANDLE)
1627			(void) C_DestroyObject(hSession, pubKey);
1628		if (priKey != CK_INVALID_HANDLE)
1629			(void) C_DestroyObject(hSession, priKey);
1630		if (privkey) {
1631			privkey->keyp = NULL;
1632			if (privkey->keylabel)
1633				free(privkey->keylabel);
1634		}
1635		if (pubkey) {
1636			pubkey->keyp = NULL;
1637			if (pubkey->keylabel)
1638				free(pubkey->keylabel);
1639		}
1640	}
1641	return (rv);
1642}
1643
1644KMF_RETURN
1645KMFPK11_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1646	KMF_KEY_HANDLE *key, boolean_t destroy)
1647{
1648	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1649	CK_RV ckrv = CKR_OK;
1650	KMF_RETURN rv = KMF_OK;
1651
1652	if (!kmfh)
1653		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1654
1655	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1656		return (KMF_ERR_NO_TOKEN_SELECTED);
1657
1658	if (key == NULL || key->keyp == NULL)
1659		return (KMF_ERR_BAD_PARAMETER);
1660
1661	if (key->keyclass != KMF_ASYM_PUB &&
1662		key->keyclass != KMF_ASYM_PRI &&
1663		key->keyclass != KMF_SYMMETRIC)
1664		return (KMF_ERR_BAD_KEY_CLASS);
1665
1666	if (destroy) {
1667		rv = pk11_authenticate(handle, &params->cred);
1668		if (rv != KMF_OK) {
1669			return (rv);
1670		}
1671	}
1672
1673	if (!key->israw && destroy)
1674		ckrv = C_DestroyObject(kmfh->pk11handle,
1675			(CK_OBJECT_HANDLE)key->keyp);
1676
1677	if (ckrv != CKR_OK) {
1678		SET_ERROR(kmfh, ckrv);
1679		/* Report authentication failures to the caller */
1680		if (ckrv == CKR_PIN_EXPIRED ||
1681		    ckrv == CKR_SESSION_READ_ONLY)
1682			rv = KMF_ERR_AUTH_FAILED;
1683		else
1684			rv = KMF_ERR_INTERNAL;
1685	}
1686	return (rv);
1687
1688}
1689
1690KMF_RETURN
1691KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1692	KMF_OID *algOID,
1693	KMF_DATA *tobesigned,
1694	KMF_DATA *output)
1695{
1696	CK_RV			ckrv;
1697	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1698	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1699	CK_MECHANISM		mechanism;
1700	PKCS_ALGORITHM_MAP 	*pAlgMap;
1701	KMF_ALGORITHM_INDEX		AlgId;
1702
1703	if (!kmfh)
1704		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1705
1706	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1707		return (KMF_ERR_NO_TOKEN_SELECTED);
1708
1709	if (keyp == NULL || algOID == NULL ||
1710	    tobesigned == NULL || output == NULL)
1711		return (KMF_ERR_BAD_PARAMETER);
1712
1713	/* These functions are available to the plugin from libkmf */
1714	AlgId = X509_AlgorithmOidToAlgId(algOID);
1715	if (AlgId == KMF_ALGID_NONE)
1716		return (KMF_ERR_BAD_PARAMETER);
1717
1718	/* Map the Algorithm OID to a PKCS#11 mechanism */
1719	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1720		AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1721
1722	if (pAlgMap == NULL)
1723		return (KMF_ERR_BAD_PARAMETER);
1724
1725	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1726	mechanism.pParameter = NULL;
1727	mechanism.ulParameterLen = 0;
1728
1729	ckrv = C_SignInit(hSession, &mechanism, (CK_OBJECT_HANDLE)keyp->keyp);
1730	if (ckrv != CKR_OK) {
1731		SET_ERROR(kmfh, ckrv);
1732		return (KMF_ERR_INTERNAL);
1733	}
1734
1735	ckrv = C_Sign(hSession,
1736		tobesigned->Data, tobesigned->Length,
1737		output->Data, (CK_ULONG *)&output->Length);
1738
1739	if (ckrv != CKR_OK) {
1740		SET_ERROR(kmfh, ckrv);
1741		return (KMF_ERR_INTERNAL);
1742	}
1743
1744	return (KMF_OK);
1745}
1746
1747KMF_RETURN
1748KMFPK11_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1749{
1750	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1751
1752	*msgstr = NULL;
1753	if (kmfh->lasterr.errcode != 0) {
1754		char *e = pkcs11_strerror(kmfh->lasterr.errcode);
1755		if (e == NULL || (*msgstr = (char *)strdup(e)) == NULL) {
1756			return (KMF_ERR_MEMORY);
1757		}
1758	}
1759
1760	return (KMF_OK);
1761}
1762
1763static CK_RV
1764getObjectKeytype(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1765	CK_ULONG *keytype)
1766{
1767	CK_RV rv = CKR_OK;
1768	CK_ATTRIBUTE templ;
1769	CK_ULONG len = sizeof (CK_ULONG);
1770	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1771
1772	templ.type = CKA_KEY_TYPE;
1773	templ.pValue = keytype;
1774	templ.ulValueLen = len;
1775
1776	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1777
1778	return (rv);
1779
1780}
1781static CK_RV
1782getObjectLabel(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1783	char **outlabel)
1784{
1785	CK_RV rv = CKR_OK;
1786	CK_ATTRIBUTE templ;
1787	char	Label[BUFSIZ];
1788	CK_ULONG len = sizeof (Label);
1789	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1790
1791	(void) memset(Label, 0, len);
1792	templ.type = CKA_LABEL;
1793	templ.pValue = Label;
1794	templ.ulValueLen = len;
1795
1796	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1797	if (rv == CKR_OK) {
1798		*outlabel = (char *)strdup(Label);
1799	} else {
1800		*outlabel = NULL;
1801	}
1802	return (rv);
1803}
1804
1805KMF_RETURN
1806KMFPK11_GetPrikeyByCert(KMF_HANDLE_T handle,
1807	KMF_CRYPTOWITHCERT_PARAMS *params,
1808	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
1809	KMF_KEY_ALG keytype)
1810{
1811	KMF_X509_SPKI *pubkey;
1812	KMF_X509_CERTIFICATE *SignerCert = NULL;
1813	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1814	KMF_RETURN rv = KMF_OK;
1815	CK_RV ckrv = CKR_OK;
1816	CK_ATTRIBUTE templ[4];
1817	CK_OBJECT_HANDLE pri_obj = CK_INVALID_HANDLE;
1818	CK_ULONG obj_count;
1819	CK_OBJECT_CLASS certClass = CKO_PRIVATE_KEY;
1820	CK_BBOOL true = TRUE;
1821	KMF_DATA Id = { NULL, 0 };
1822
1823	/* Decode the signer cert so we can get the SPKI data */
1824	if ((rv = DerDecodeSignedCertificate(SignerCertData,
1825	    &SignerCert)) != KMF_OK)
1826		return (rv);
1827
1828	/* Get the public key info from the signer certificate */
1829	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
1830
1831	/* Generate an ID from the SPKI data */
1832	rv = GetIDFromSPKI(pubkey, &Id);
1833
1834	if (rv != KMF_OK) {
1835		SET_ERROR(kmfh, rv);
1836		goto errout;
1837	}
1838
1839	SETATTR(templ, 0, CKA_CLASS, &certClass, sizeof (certClass));
1840	SETATTR(templ, 1, CKA_TOKEN, &true, sizeof (true));
1841	SETATTR(templ, 2, CKA_PRIVATE, &true, sizeof (true));
1842	SETATTR(templ, 3, CKA_ID, Id.Data, Id.Length);
1843
1844	rv = pk11_authenticate(handle, &params->cred);
1845	if (rv != KMF_OK) {
1846		return (rv);
1847	}
1848
1849	if ((ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, 4)) != CKR_OK) {
1850		SET_ERROR(kmfh, ckrv);
1851		rv = KMF_ERR_INTERNAL;
1852		goto errout;
1853	}
1854
1855	if ((rv = C_FindObjects(kmfh->pk11handle, &pri_obj, 1,
1856	    &obj_count)) != CKR_OK) {
1857		SET_ERROR(kmfh, ckrv);
1858		rv = KMF_ERR_INTERNAL;
1859		goto errout;
1860	}
1861
1862	if (obj_count == 0) {
1863		SET_ERROR(kmfh, ckrv);
1864		rv = KMF_ERR_INTERNAL;
1865		goto errout;
1866	}
1867
1868	key->kstype = KMF_KEYSTORE_PK11TOKEN;
1869	key->keyclass = KMF_ASYM_PRI;
1870	key->keyalg = keytype;
1871	key->keyp = (void *)pri_obj;
1872
1873	(void) C_FindObjectsFinal(kmfh->pk11handle);
1874
1875	ckrv = getObjectLabel(handle, (CK_OBJECT_HANDLE)key->keyp,
1876		&key->keylabel);
1877
1878	if (ckrv != CKR_OK) {
1879		SET_ERROR(handle, ckrv);
1880		rv = KMF_ERR_INTERNAL;
1881	} else {
1882		rv = KMF_OK;
1883	}
1884
1885	if (rv == KMF_OK && params->format == KMF_FORMAT_RAWKEY) {
1886		KMF_RAW_KEY_DATA *rkey = NULL;
1887		rv = keyObj2RawKey(handle, key, &rkey);
1888		if (rv == KMF_OK) {
1889			key->keyp = rkey;
1890			key->israw = TRUE;
1891		}
1892	}
1893
1894errout:
1895	if (Id.Data != NULL)
1896		free(Id.Data);
1897
1898	if (SignerCert != NULL) {
1899		KMF_FreeSignedCert(SignerCert);
1900		free(SignerCert);
1901	}
1902	return (rv);
1903}
1904
1905KMF_RETURN
1906KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1907	KMF_OID *algOID, KMF_DATA *ciphertext,
1908	KMF_DATA *output)
1909{
1910	CK_RV			ckrv;
1911	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1912	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1913	CK_MECHANISM		mechanism;
1914	PKCS_ALGORITHM_MAP 	*pAlgMap;
1915	KMF_ALGORITHM_INDEX	AlgId;
1916	CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
1917	uint8_t *in_data, *out_data;
1918	int i, blocks;
1919	CK_ATTRIBUTE ckTemplate[1];
1920
1921	if (!kmfh)
1922		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1923
1924	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1925		return (KMF_ERR_NO_TOKEN_SELECTED);
1926
1927	if (key == NULL || algOID == NULL ||
1928	    ciphertext == NULL || output == NULL)
1929		return (KMF_ERR_BAD_PARAMETER);
1930
1931	AlgId = X509_AlgorithmOidToAlgId(algOID);
1932	if (AlgId == KMF_ALGID_NONE)
1933		return (KMF_ERR_BAD_PARAMETER);
1934
1935	/* Map the Algorithm ID to a PKCS#11 mechanism */
1936	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1937	    AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1938
1939	if (pAlgMap == NULL)
1940		return (KMF_ERR_BAD_PARAMETER);
1941
1942	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1943	mechanism.pParameter = NULL;
1944	mechanism.ulParameterLen = 0;
1945
1946	SETATTR(ckTemplate, 0, CKA_MODULUS, (CK_BYTE *)NULL,
1947	    sizeof (CK_ULONG));
1948
1949	/* Get the modulus length */
1950	ckrv = C_GetAttributeValue(hSession,
1951	    (CK_OBJECT_HANDLE)key->keyp, ckTemplate, 1);
1952
1953	if (ckrv != CKR_OK)  {
1954		SET_ERROR(kmfh, ckrv);
1955		return (KMF_ERR_INTERNAL);
1956	}
1957
1958	block_len = ckTemplate[0].ulValueLen;
1959
1960	/* Compute the number of times to do single-part decryption */
1961	blocks = ciphertext->Length/block_len;
1962
1963	out_data = output->Data;
1964	in_data = ciphertext->Data;
1965	out_len = block_len - 11;
1966
1967	for (i = 0; i < blocks; i++) {
1968		ckrv = C_DecryptInit(hSession, &mechanism,
1969			(CK_OBJECT_HANDLE)key->keyp);
1970
1971		if (ckrv != CKR_OK) {
1972			SET_ERROR(kmfh, ckrv);
1973			return (KMF_ERR_INTERNAL);
1974		}
1975
1976		ckrv = C_Decrypt(hSession, in_data, block_len,
1977		    out_data, (CK_ULONG *)&out_len);
1978
1979		if (ckrv != CKR_OK) {
1980			SET_ERROR(kmfh, ckrv);
1981			return (KMF_ERR_INTERNAL);
1982		}
1983
1984		out_data += out_len;
1985		total_decrypted += out_len;
1986		in_data += block_len;
1987
1988	}
1989
1990	output->Length = total_decrypted;
1991	return (KMF_OK);
1992}
1993
1994static void
1995attr2bigint(CK_ATTRIBUTE_PTR attr, KMF_BIGINT *big)
1996{
1997	big->val = attr->pValue;
1998	big->len = attr->ulValueLen;
1999}
2000
2001
2002static KMF_RETURN
2003get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2004{
2005	KMF_RETURN rv = KMF_OK;
2006	CK_RV ckrv;
2007	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2008	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
2009		{ CKA_MODULUS, NULL, 0 },
2010		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
2011		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
2012		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
2013		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
2014		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
2015		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
2016		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
2017	    };
2018	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2019	int		i;
2020
2021	if ((ckrv = C_GetAttributeValue(sess, obj,
2022			rsa_pri_attrs, count)) != CKR_OK) {
2023		SET_ERROR(kmfh, ckrv);
2024		/* Tell the caller know why the key data cannot be retrieved. */
2025		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2026			return (KMF_ERR_SENSITIVE_KEY);
2027		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2028			return (KMF_ERR_UNEXTRACTABLE_KEY);
2029		else
2030			return (KMF_ERR_INTERNAL);
2031	}
2032
2033	/* Allocate memory for each attribute. */
2034	for (i = 0; i < count; i++) {
2035		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2036		    rsa_pri_attrs[i].ulValueLen == 0) {
2037			rsa_pri_attrs[i].ulValueLen = 0;
2038			continue;
2039		}
2040		if ((rsa_pri_attrs[i].pValue =
2041		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2042			rv = KMF_ERR_MEMORY;
2043			goto end;
2044		}
2045	}
2046	/* Now that we have space, really get the attributes */
2047	if ((rv = C_GetAttributeValue(sess, obj,
2048			rsa_pri_attrs, count)) != CKR_OK) {
2049		SET_ERROR(kmfh, rv);
2050		rv = KMF_ERR_INTERNAL;
2051		goto end;
2052	}
2053	i = 0;
2054	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2055	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2056
2057	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2058	    rsa_pri_attrs[i].ulValueLen != 0)
2059		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->priexp);
2060	i++;
2061
2062	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2063	    rsa_pri_attrs[i].ulValueLen != 0)
2064		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime1);
2065	i++;
2066
2067	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2068	    rsa_pri_attrs[i].ulValueLen != 0)
2069		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime2);
2070	i++;
2071
2072	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2073	    rsa_pri_attrs[i].ulValueLen != 0)
2074		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp1);
2075	i++;
2076
2077	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2078	    rsa_pri_attrs[i].ulValueLen != 0)
2079		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp2);
2080	i++;
2081
2082	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2083	    rsa_pri_attrs[i].ulValueLen != 0)
2084		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->coef);
2085	i++;
2086
2087end:
2088	if (rv != KMF_OK) {
2089		for (i = 0; i < count; i++) {
2090			if (rsa_pri_attrs[i].pValue != NULL)
2091				free(rsa_pri_attrs[i].pValue);
2092		}
2093		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2094	}
2095	return (rv);
2096}
2097
2098static KMF_RETURN
2099get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2100{
2101	KMF_RETURN rv = KMF_OK;
2102	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2103	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2104		{ CKA_PRIME, NULL, 0 },
2105		{ CKA_SUBPRIME, NULL, 0 },
2106		{ CKA_BASE, NULL, 0 },
2107		{ CKA_VALUE, NULL, 0 }
2108	};
2109	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2110	int		i;
2111
2112	if ((rv = C_GetAttributeValue(sess, obj,
2113		dsa_pri_attrs, count)) != CKR_OK) {
2114		SET_ERROR(kmfh, rv);
2115		return (KMF_ERR_INTERNAL);
2116	}
2117
2118	/* Allocate memory for each attribute. */
2119	for (i = 0; i < count; i++) {
2120		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2121		    dsa_pri_attrs[i].ulValueLen == 0) {
2122			dsa_pri_attrs[i].ulValueLen = 0;
2123			continue;
2124		}
2125		if ((dsa_pri_attrs[i].pValue =
2126		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2127			rv = KMF_ERR_MEMORY;
2128			goto end;
2129		}
2130	}
2131	if ((rv = C_GetAttributeValue(sess, obj,
2132		dsa_pri_attrs, count)) != CKR_OK) {
2133		SET_ERROR(kmfh, rv);
2134		rv = KMF_ERR_INTERNAL;
2135		goto end;
2136	}
2137
2138	/* Fill in all the temp variables.  They are all required. */
2139	i = 0;
2140	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2141	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2142	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2143	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2144
2145end:
2146	if (rv != KMF_OK) {
2147		for (i = 0; i < count; i++) {
2148			if (dsa_pri_attrs[i].pValue != NULL)
2149				free(dsa_pri_attrs[i].pValue);
2150		}
2151		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2152	}
2153	return (rv);
2154}
2155
2156static KMF_RETURN
2157get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2158{
2159	KMF_RETURN rv = KMF_OK;
2160	CK_RV	ckrv;
2161	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2162	CK_ATTRIBUTE	sym_attr[1];
2163	CK_ULONG	value_len = 0;
2164
2165	/* find the key length first */
2166	sym_attr[0].type = CKA_VALUE;
2167	sym_attr[0].pValue = NULL;
2168	sym_attr[0].ulValueLen = value_len;
2169	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2170		/*
2171		 * Don't return error if the key is sensitive, just
2172		 * don't return any raw data.  Operations like "list"
2173		 * need to succeed even if the raw data is not
2174		 * available.
2175		 */
2176		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2177			rawsym->keydata.val = NULL;
2178			rawsym->keydata.len = 0;
2179			return (CKR_OK);
2180		}
2181		SET_ERROR(kmfh, ckrv);
2182		return (KMF_ERR_INTERNAL);
2183	}
2184
2185	/* Allocate memory for pValue */
2186	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2187	if (sym_attr[0].pValue == NULL) {
2188		return (KMF_ERR_MEMORY);
2189	}
2190
2191	/* get the key data */
2192	if ((rv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2193		SET_ERROR(kmfh, rv);
2194		free(sym_attr[0].pValue);
2195		return (KMF_ERR_INTERNAL);
2196	}
2197
2198	rawsym->keydata.val = sym_attr[0].pValue;
2199	rawsym->keydata.len = sym_attr[0].ulValueLen;
2200	return (rv);
2201}
2202
2203static KMF_RETURN
2204keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2205	KMF_RAW_KEY_DATA **outkey)
2206{
2207	KMF_RETURN rv = KMF_OK;
2208	KMF_RAW_KEY_DATA *rkey;
2209	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2210
2211	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2212	if (rkey == NULL)
2213		return (KMF_ERR_MEMORY);
2214
2215	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2216
2217	rkey->keytype = inkey->keyalg;
2218
2219	if (inkey->keyalg == KMF_RSA) {
2220		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2221			&rkey->rawdata.rsa);
2222	} else if (inkey->keyalg == KMF_DSA) {
2223		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2224			&rkey->rawdata.dsa);
2225	} else if (inkey->keyalg == KMF_AES ||
2226	    inkey->keyalg == KMF_RC4 ||
2227	    inkey->keyalg == KMF_DES ||
2228	    inkey->keyalg == KMF_DES3) {
2229		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2230		    &rkey->rawdata.sym);
2231	} else {
2232		rv = KMF_ERR_BAD_PARAMETER;
2233	}
2234
2235	if (rv == KMF_OK) {
2236		*outkey = rkey;
2237	} else if (rkey != NULL) {
2238		free(rkey);
2239		*outkey = NULL;
2240	}
2241
2242	return (rv);
2243}
2244
2245
2246static KMF_RETURN
2247kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2248{
2249	switch (keyalg) {
2250	case KMF_RSA:
2251		*type = CKK_RSA;
2252		break;
2253	case KMF_DSA:
2254		*type = CKK_DSA;
2255		break;
2256	case KMF_AES:
2257		*type = CKK_AES;
2258		break;
2259	case KMF_RC4:
2260		*type = CKK_RC4;
2261		break;
2262	case KMF_DES:
2263		*type = CKK_DES;
2264		break;
2265	case KMF_DES3:
2266		*type = CKK_DES3;
2267		break;
2268	default:
2269		return (KMF_ERR_BAD_KEY_TYPE);
2270	}
2271
2272	return (KMF_OK);
2273}
2274
2275static int
2276IDStringToData(char *idstr, KMF_DATA *iddata)
2277{
2278	int len, i;
2279	char *iddup, *byte;
2280	uint_t lvalue;
2281
2282	if (idstr == NULL || !strlen(idstr))
2283		return (-1);
2284
2285	iddup = (char *)strdup(idstr);
2286	if (iddup == NULL)
2287		return (KMF_ERR_MEMORY);
2288
2289	len = strlen(iddup) / 3  + 1;
2290	iddata->Data = malloc(len);
2291	if (iddata->Data == NULL)
2292		return (KMF_ERR_MEMORY);
2293	(void) memset(iddata->Data, 0, len);
2294	iddata->Length = len;
2295
2296	byte = strtok(iddup, ":");
2297	if (byte == NULL) {
2298		free(iddup);
2299		free(iddata->Data);
2300		iddata->Data = NULL;
2301		iddata->Length = 0;
2302		return (-1);
2303	}
2304
2305	i = 0;
2306	do {
2307		(void) sscanf(byte, "%x", &lvalue);
2308		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2309		byte = strtok(NULL, ":");
2310	} while (byte != NULL && i < len);
2311
2312	iddata->Length = i;
2313	free(iddup);
2314	return (0);
2315}
2316
2317KMF_RETURN
2318KMFPK11_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
2319	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
2320{
2321	KMF_RETURN rv = KMF_OK;
2322	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2323	uint32_t want_keys, i;
2324	CK_RV ckrv;
2325	CK_ATTRIBUTE pTmpl[10];
2326	CK_OBJECT_CLASS class;
2327	CK_BBOOL true = TRUE;
2328	CK_ULONG alg;
2329	CK_BBOOL is_token;
2330
2331	if (!kmfh)
2332		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2333
2334	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2335		return (KMF_ERR_NO_TOKEN_SELECTED);
2336
2337	if (parms == NULL || numkeys == NULL)
2338		return (KMF_ERR_BAD_PARAMETER);
2339
2340	if (numkeys != NULL && *numkeys > 0)
2341		want_keys = *numkeys;
2342	else
2343		want_keys = MAXINT; /* count them all */
2344
2345	is_token = parms->pkcs11parms.token;
2346	if (parms->keyclass == KMF_ASYM_PUB) {
2347		class = CKO_PUBLIC_KEY;
2348	} else if (parms->keyclass == KMF_ASYM_PRI) {
2349		class = CKO_PRIVATE_KEY;
2350	} else if (parms->keyclass == KMF_SYMMETRIC) {
2351		class = CKO_SECRET_KEY;
2352	} else {
2353		return (KMF_ERR_BAD_KEY_CLASS);
2354	}
2355
2356	i = 0;
2357	pTmpl[i].type = CKA_TOKEN;
2358	pTmpl[i].pValue = &is_token;
2359	pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
2360	i++;
2361
2362	pTmpl[i].type = CKA_CLASS;
2363	pTmpl[i].pValue = &class;
2364	pTmpl[i].ulValueLen = sizeof (class);
2365	i++;
2366
2367	if (parms->findLabel != NULL && strlen(parms->findLabel)) {
2368		pTmpl[i].type = CKA_LABEL;
2369		pTmpl[i].pValue = parms->findLabel;
2370		pTmpl[i].ulValueLen = strlen(parms->findLabel);
2371		i++;
2372	}
2373
2374	if (parms->keytype != 0) {
2375		rv = kmf2pk11keytype(parms->keytype, &alg);
2376		if (rv != KMF_OK) {
2377			return (KMF_ERR_BAD_KEY_TYPE);
2378		}
2379		pTmpl[i].type = CKA_KEY_TYPE;
2380		pTmpl[i].pValue = &alg;
2381		pTmpl[i].ulValueLen = sizeof (alg);
2382		i++;
2383	}
2384
2385	if (parms->idstr != NULL) {
2386		KMF_DATA iddata = { NULL, 0 };
2387
2388		/*
2389		 * ID String parameter is assumed to be of form:
2390		 * XX:XX:XX:XX:XX ... :XX
2391		 * where XX is a hex number.
2392		 *
2393		 * We must convert this back to binary in order to
2394		 * use it in a search.
2395		 */
2396		rv = IDStringToData(parms->idstr, &iddata);
2397		if (rv == KMF_OK) {
2398			pTmpl[i].type = CKA_ID;
2399			pTmpl[i].pValue = iddata.Data;
2400			pTmpl[i].ulValueLen = iddata.Length;
2401			i++;
2402		} else {
2403			return (rv);
2404		}
2405	}
2406
2407	if (parms->pkcs11parms.private) {
2408		pTmpl[i].type = CKA_PRIVATE;
2409		pTmpl[i].pValue = &true;
2410		pTmpl[i].ulValueLen = sizeof (true);
2411		i++;
2412	}
2413
2414	/*
2415	 * Authenticate if the object is a token object,
2416	 * a private or secred key, or if the user passed in credentials.
2417	 */
2418	if (parms->cred.credlen > 0) {
2419		rv = pk11_authenticate(handle, &parms->cred);
2420		if (rv != KMF_OK) {
2421			return (rv);
2422		}
2423	}
2424
2425	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2426	if (ckrv == CKR_OK) {
2427		CK_ULONG obj_count, n = 0;
2428		while (ckrv == CKR_OK && n < want_keys) {
2429			CK_OBJECT_HANDLE hObj;
2430
2431			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2432				1, &obj_count);
2433			if (ckrv == CKR_OK && obj_count == 1) {
2434				if (keys != NULL) {
2435					CK_ULONG keytype;
2436					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2437					keys[n].keyclass = parms->keyclass;
2438					keys[n].israw = FALSE;
2439					keys[n].keyp = (void *)hObj;
2440
2441					ckrv = getObjectKeytype(handle,
2442						(CK_OBJECT_HANDLE)keys[n].keyp,
2443						&keytype);
2444					if (ckrv != CKR_OK)
2445						goto end;
2446
2447					ckrv = getObjectLabel(handle,
2448						(CK_OBJECT_HANDLE)keys[n].keyp,
2449						&(keys[n].keylabel));
2450					if (ckrv != CKR_OK)
2451						goto end;
2452
2453					if (keytype == CKK_RSA)
2454						keys[n].keyalg = KMF_RSA;
2455					else if (keytype == CKK_DSA)
2456						keys[n].keyalg = KMF_DSA;
2457					else if (keytype == CKK_AES)
2458						keys[n].keyalg = KMF_AES;
2459					else if (keytype == CKK_RC4)
2460						keys[n].keyalg = KMF_RC4;
2461					else if (keytype == CKK_DES)
2462						keys[n].keyalg = KMF_DES;
2463					else if (keytype == CKK_DES3)
2464						keys[n].keyalg = KMF_DES3;
2465
2466				}
2467				n++;
2468			} else {
2469				break;
2470			}
2471		}
2472		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2473
2474		/* "numkeys" indicates the number that were actually found */
2475		*numkeys = n;
2476	}
2477	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
2478		if (parms->format == KMF_FORMAT_RAWKEY) {
2479			/* Convert keys to "rawkey" format */
2480			for (i = 0; i < (*numkeys); i++) {
2481				KMF_RAW_KEY_DATA *rkey = NULL;
2482				rv = keyObj2RawKey(handle, &keys[i], &rkey);
2483				if (rv == KMF_OK) {
2484					keys[i].keyp = rkey;
2485					keys[i].israw = TRUE;
2486				} else {
2487					break;
2488				}
2489			}
2490		}
2491	}
2492end:
2493	if (ckrv != CKR_OK) {
2494		SET_ERROR(kmfh, ckrv);
2495		/* Report authentication failures to the caller */
2496		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2497		    ckrv == CKR_PIN_INCORRECT ||
2498		    ckrv == CKR_PIN_INVALID ||
2499		    ckrv == CKR_PIN_EXPIRED ||
2500		    ckrv == CKR_PIN_LOCKED ||
2501		    ckrv == CKR_SESSION_READ_ONLY)
2502			rv = KMF_ERR_AUTH_FAILED;
2503		else
2504			rv = KMF_ERR_INTERNAL;
2505	} else if ((*numkeys) == 0) {
2506		rv = KMF_ERR_KEY_NOT_FOUND;
2507	}
2508
2509	return (rv);
2510}
2511
2512static char *
2513convertDate(char *fulldate)
2514{
2515	struct tm tms;
2516	char newtime[9];
2517
2518	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2519
2520	if (tms.tm_year < 69)
2521		tms.tm_year += 100;
2522
2523	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2524
2525	newtime[8] = 0;
2526
2527	/* memory returned must be freed by the caller */
2528	return ((char *)strdup(newtime));
2529}
2530
2531KMF_RETURN
2532KMFPK11_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2533	KMF_RAW_KEY_DATA *rawkey)
2534{
2535	KMF_RETURN rv = KMF_OK;
2536	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2537	int i;
2538	CK_RV		ckrv = CKR_OK;
2539	CK_ATTRIBUTE	templ[32];
2540	CK_OBJECT_HANDLE keyobj;
2541	CK_KEY_TYPE	keytype;
2542	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2543	CK_BBOOL	cktrue = TRUE;
2544	CK_DATE		startdate, enddate;
2545	KMF_DATA	id = {NULL, 0};
2546	KMF_DATA	subject = {NULL, 0};
2547	KMF_X509EXT_KEY_USAGE kuext;
2548	KMF_X509_CERTIFICATE *x509 = NULL;
2549	CK_BBOOL	kufound;
2550	char		*notbefore = NULL, *start = NULL;
2551	char		*notafter = NULL, *end = NULL;
2552
2553	if (!kmfh)
2554		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2555
2556	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2557		return (KMF_ERR_NO_TOKEN_SELECTED);
2558
2559	if (params == NULL || params->certificate == NULL ||
2560		rawkey == NULL)
2561		return (KMF_ERR_BAD_PARAMETER);
2562
2563	if (rawkey->keytype == KMF_RSA)
2564		keytype = CKK_RSA;
2565	else if (rawkey->keytype == KMF_DSA)
2566		keytype = CKK_DSA;
2567	else
2568		return (KMF_ERR_BAD_PARAMETER);
2569
2570	rv = pk11_authenticate(handle, &params->cred);
2571	if (rv != KMF_OK) {
2572		return (rv);
2573	}
2574
2575	id.Data = NULL;
2576	id.Length = 0;
2577	rv = KMF_GetCertIDData(params->certificate, &id);
2578	if (rv != KMF_OK) {
2579		goto cleanup;
2580	}
2581
2582	rv = DerDecodeSignedCertificate(
2583		(const KMF_DATA *)params->certificate, &x509);
2584	if (rv != KMF_OK) {
2585		goto cleanup;
2586	}
2587
2588	rv = DerEncodeName(&x509->certificate.subject, &subject);
2589	if (rv != KMF_OK) {
2590		goto cleanup;
2591	}
2592
2593	rv = KMF_GetCertStartDateString(handle, params->certificate,
2594		&notbefore);
2595	if (rv != KMF_OK) {
2596		goto cleanup;
2597	}
2598	start = convertDate(notbefore);
2599
2600	rv = KMF_GetCertEndDateString(handle, params->certificate,
2601		&notafter);
2602	if (rv != KMF_OK) {
2603		goto cleanup;
2604	}
2605	end = convertDate(notafter);
2606
2607	if ((rv = KMF_GetCertKeyUsageExt(params->certificate, &kuext))
2608		!= KMF_OK && rv != KMF_ERR_EXTENSION_NOT_FOUND)
2609		goto cleanup;
2610
2611	kufound = (rv == KMF_OK);
2612	rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND above */
2613
2614	i = 0;
2615	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2616	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2617	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2618	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2619	SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++;
2620	SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
2621
2622	/*
2623	 * Only set the KeyUsage stuff if the KU extension was present.
2624	 */
2625	if (kufound) {
2626		CK_BBOOL	condition;
2627
2628		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
2629			B_TRUE : B_FALSE;
2630		SETATTR(templ, i, CKA_UNWRAP, &condition,
2631			sizeof (CK_BBOOL)); i++;
2632		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
2633			B_TRUE : B_FALSE;
2634		SETATTR(templ, i, CKA_DECRYPT, &condition,
2635			sizeof (CK_BBOOL)); i++;
2636		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2637			B_TRUE : B_FALSE;
2638		SETATTR(templ, i, CKA_SIGN, &condition,
2639			sizeof (CK_BBOOL)); i++;
2640		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2641			B_TRUE : B_FALSE;
2642		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
2643			sizeof (CK_BBOOL)); i++;
2644	}
2645	if (params->label != NULL) {
2646		SETATTR(templ, i, CKA_LABEL, params->label,
2647			strlen(params->label));
2648		i++;
2649	}
2650	if (id.Data != NULL &&
2651		id.Data != NULL && id.Length > 0) {
2652		SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2653		i++;
2654	}
2655	if (start != NULL) {
2656		/*
2657		 * This make some potentially dangerous assumptions:
2658		 *  1. that the startdate in the parameter block is
2659		 * properly formatted as YYYYMMDD
2660		 *  2. That the CK_DATE structure is always the same.
2661		 */
2662		(void) memcpy(&startdate, start, sizeof (CK_DATE));
2663		SETATTR(templ, i, CKA_START_DATE, &startdate,
2664			sizeof (startdate));
2665		i++;
2666	}
2667	if (end != NULL) {
2668		(void) memcpy(&enddate, end, sizeof (CK_DATE));
2669		SETATTR(templ, i, CKA_END_DATE, &enddate, sizeof (enddate));
2670		i++;
2671	}
2672	if (keytype == CKK_RSA) {
2673		SETATTR(templ, i, CKA_MODULUS,
2674			rawkey->rawdata.rsa.mod.val,
2675			rawkey->rawdata.rsa.mod.len);
2676		i++;
2677		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
2678			rawkey->rawdata.rsa.pubexp.val,
2679			rawkey->rawdata.rsa.pubexp.len);
2680		i++;
2681		if (rawkey->rawdata.rsa.priexp.val != NULL) {
2682			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
2683				rawkey->rawdata.rsa.priexp.val,
2684				rawkey->rawdata.rsa.priexp.len);
2685			i++;
2686		}
2687		if (rawkey->rawdata.rsa.prime1.val != NULL) {
2688			SETATTR(templ, i, CKA_PRIME_1,
2689				rawkey->rawdata.rsa.prime1.val,
2690				rawkey->rawdata.rsa.prime1.len);
2691			i++;
2692		}
2693		if (rawkey->rawdata.rsa.prime2.val != NULL) {
2694			SETATTR(templ, i, CKA_PRIME_2,
2695				rawkey->rawdata.rsa.prime2.val,
2696				rawkey->rawdata.rsa.prime2.len);
2697			i++;
2698		}
2699		if (rawkey->rawdata.rsa.exp1.val != NULL) {
2700			SETATTR(templ, i, CKA_EXPONENT_1,
2701				rawkey->rawdata.rsa.exp1.val,
2702				rawkey->rawdata.rsa.exp1.len);
2703			i++;
2704		}
2705		if (rawkey->rawdata.rsa.exp2.val != NULL) {
2706			SETATTR(templ, i, CKA_EXPONENT_2,
2707				rawkey->rawdata.rsa.exp2.val,
2708				rawkey->rawdata.rsa.exp2.len);
2709			i++;
2710		}
2711		if (rawkey->rawdata.rsa.coef.val != NULL) {
2712			SETATTR(templ, i, CKA_COEFFICIENT,
2713				rawkey->rawdata.rsa.coef.val,
2714				rawkey->rawdata.rsa.coef.len);
2715			i++;
2716		}
2717	} else {
2718		SETATTR(templ, i, CKA_PRIME,
2719			rawkey->rawdata.dsa.prime.val,
2720			rawkey->rawdata.dsa.prime.len);
2721		i++;
2722		SETATTR(templ, i, CKA_SUBPRIME,
2723			rawkey->rawdata.dsa.subprime.val,
2724			rawkey->rawdata.dsa.subprime.len);
2725		i++;
2726		SETATTR(templ, i, CKA_BASE,
2727			rawkey->rawdata.dsa.base.val,
2728			rawkey->rawdata.dsa.base.len);
2729		i++;
2730		SETATTR(templ, i, CKA_VALUE,
2731			rawkey->rawdata.dsa.value.val,
2732			rawkey->rawdata.dsa.value.len);
2733		i++;
2734	}
2735
2736	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
2737	if (ckrv != CKR_OK) {
2738		SET_ERROR(kmfh, ckrv);
2739
2740		/* Report authentication failures to the caller */
2741		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2742		    ckrv == CKR_PIN_INCORRECT ||
2743		    ckrv == CKR_PIN_INVALID ||
2744		    ckrv == CKR_PIN_EXPIRED ||
2745		    ckrv == CKR_PIN_LOCKED ||
2746		    ckrv == CKR_SESSION_READ_ONLY)
2747			rv = KMF_ERR_AUTH_FAILED;
2748		else
2749			rv = KMF_ERR_INTERNAL;
2750	}
2751cleanup:
2752	KMF_FreeData(&id);
2753	KMF_FreeData(&subject);
2754	KMF_FreeSignedCert(x509);
2755	free(x509);
2756
2757	return (rv);
2758}
2759
2760KMF_RETURN
2761KMFPK11_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
2762	KMF_KEY_HANDLE *symkey)
2763{
2764	KMF_RETURN		rv = KMF_OK;
2765	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2766	CK_RV			ckrv;
2767	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2768	CK_OBJECT_HANDLE	keyhandle;
2769	CK_MECHANISM		keyGenMech;
2770	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
2771	CK_ULONG		secKeyType;
2772	CK_ULONG		secKeyLen;	/* for RC4 and AES */
2773	CK_BBOOL		true = TRUE;
2774	CK_BBOOL		false = FALSE;
2775	CK_ATTRIBUTE		templ[15];
2776	int i;
2777
2778	if (kmfh == NULL)
2779		return (KMF_ERR_UNINITIALIZED);
2780
2781	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2782		return (KMF_ERR_NO_TOKEN_SELECTED);
2783
2784	if (params == NULL)
2785		return (KMF_ERR_BAD_PARAMETER);
2786
2787	keyGenMech.pParameter = NULL_PTR;
2788	keyGenMech.ulParameterLen = 0;
2789	switch (params->keytype) {
2790	case KMF_AES:
2791		keyGenMech.mechanism = CKM_AES_KEY_GEN;
2792		secKeyType = CKK_AES;
2793		break;
2794	case KMF_RC4:
2795		keyGenMech.mechanism = CKM_RC4_KEY_GEN;
2796		secKeyType = CKK_RC4;
2797		break;
2798	case KMF_DES:
2799		keyGenMech.mechanism = CKM_DES_KEY_GEN;
2800		secKeyType = CKK_DES;
2801		break;
2802	case KMF_DES3:
2803		keyGenMech.mechanism = CKM_DES3_KEY_GEN;
2804		secKeyType = CKK_DES3;
2805		break;
2806	default:
2807		return (KMF_ERR_BAD_KEY_TYPE);
2808	}
2809
2810	i = 0;
2811	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2812	i++;
2813	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2814	i++;
2815
2816	if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
2817		if ((params->keylength % 8) != 0) {
2818			return (KMF_ERR_BAD_KEY_SIZE);
2819		}
2820		secKeyLen = params->keylength/8;  /* in bytes for RC4/AES */
2821		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
2822		    sizeof (secKeyLen));
2823		i++;
2824	}
2825
2826	if (params->keylabel != NULL) {
2827		SETATTR(templ, i, CKA_LABEL, params->keylabel,
2828		    strlen(params->keylabel));
2829		i++;
2830	}
2831
2832	if (params->pkcs11parms.sensitive == B_TRUE) {
2833		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2834	} else {
2835		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2836	}
2837	i++;
2838
2839	if (params->pkcs11parms.not_extractable == B_TRUE) {
2840		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2841	} else {
2842		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2843	}
2844	i++;
2845
2846	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2847	i++;
2848	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2849	i++;
2850	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
2851	i++;
2852	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
2853	i++;
2854	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2855	i++;
2856	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
2857	i++;
2858
2859	rv = pk11_authenticate(handle, &params->cred);
2860	if (rv != KMF_OK) {
2861		return (rv);
2862	}
2863
2864	ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i, &keyhandle);
2865	if (ckrv != CKR_OK) {
2866		SET_ERROR(kmfh, ckrv);
2867		rv = KMF_ERR_KEYGEN_FAILED;
2868		goto out;
2869	}
2870
2871	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2872	symkey->keyalg = params->keytype;
2873	symkey->keyclass = KMF_SYMMETRIC;
2874	symkey->israw = FALSE;
2875	symkey->keyp = (void *)keyhandle;
2876
2877out:
2878	return (rv);
2879}
2880
2881
2882KMF_RETURN
2883KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2884    KMF_RAW_SYM_KEY *rkey)
2885{
2886	KMF_RETURN		rv = KMF_OK;
2887	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2888
2889	if (kmfh == NULL)
2890		return (KMF_ERR_UNINITIALIZED);
2891
2892	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2893		return (KMF_ERR_NO_TOKEN_SELECTED);
2894
2895	if (symkey == NULL || rkey == NULL)
2896		return (KMF_ERR_BAD_PARAMETER);
2897	else if (symkey->keyclass != KMF_SYMMETRIC)
2898		return (KMF_ERR_BAD_KEY_CLASS);
2899
2900	if (symkey->israw) {
2901		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2902
2903		if (rawkey == NULL ||
2904		    rawkey->rawdata.sym.keydata.val == NULL ||
2905		    rawkey->rawdata.sym.keydata.len == 0)
2906			return (KMF_ERR_BAD_KEYHANDLE);
2907
2908		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2909		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2910			return (KMF_ERR_MEMORY);
2911		(void) memcpy(rkey->keydata.val,
2912			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2913	} else {
2914		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
2915	}
2916
2917	return (rv);
2918}
2919
2920KMF_RETURN
2921KMFPK11_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2922	KMF_CREDENTIAL *newpin)
2923{
2924	KMF_RETURN	ret = KMF_OK;
2925	CK_RV		rv = CKR_OK;
2926	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
2927	CK_SESSION_HANDLE	session = NULL;
2928
2929	if (handle == NULL || params == NULL || newpin == NULL)
2930		return (KMF_ERR_BAD_PARAMETER);
2931
2932	rv = C_OpenSession(params->pkcs11parms.slot,
2933		CKF_SERIAL_SESSION | CKF_RW_SESSION,
2934		NULL, NULL, &session);
2935	if (rv != CKR_OK) {
2936		SET_ERROR(kmfh, rv);
2937		ret = KMF_ERR_UNINITIALIZED;
2938		goto end;
2939	}
2940
2941	rv = C_SetPIN(session,
2942		(CK_BYTE *)params->cred.cred, params->cred.credlen,
2943		(CK_BYTE *)newpin->cred, newpin->credlen);
2944
2945	if (rv != CKR_OK) {
2946		SET_ERROR(kmfh, rv);
2947		if (rv == CKR_PIN_INCORRECT ||
2948		    rv == CKR_PIN_INVALID ||
2949		    rv == CKR_PIN_EXPIRED ||
2950		    rv == CKR_PIN_LOCKED)
2951			ret = KMF_ERR_AUTH_FAILED;
2952		else
2953			ret = KMF_ERR_INTERNAL;
2954	}
2955end:
2956	if (session != NULL)
2957		(void) C_CloseSession(session);
2958	return (ret);
2959}
2960
2961static KMF_RETURN
2962create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
2963	CK_FLAGS wanted_flags)
2964{
2965	CK_RV rv;
2966	KMF_RETURN kmf_rv = KMF_OK;
2967	CK_SLOT_ID_PTR pSlotList;
2968	CK_ULONG pulCount;
2969	CK_MECHANISM_INFO info;
2970	int i;
2971
2972	rv = C_Initialize(NULL);
2973	if ((rv != CKR_OK) &&
2974	    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
2975		kmf_rv = KMF_ERR_UNINITIALIZED;
2976		goto out;
2977	}
2978
2979	rv = C_GetSlotList(0, NULL, &pulCount);
2980	if (rv != CKR_OK) {
2981		kmf_rv = KMF_ERR_UNINITIALIZED;
2982		goto out;
2983	}
2984
2985	pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
2986	if (pSlotList == NULL) {
2987		kmf_rv = KMF_ERR_MEMORY;
2988		goto out;
2989	}
2990
2991	rv = C_GetSlotList(0, pSlotList, &pulCount);
2992	if (rv != CKR_OK) {
2993		kmf_rv = KMF_ERR_UNINITIALIZED;
2994		goto out;
2995	}
2996
2997	for (i = 0; i < pulCount; i++) {
2998		rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
2999		if (rv == CKR_OK && (info.flags & wanted_flags))
3000			break;
3001	}
3002	if (i < pulCount) {
3003		rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
3004			NULL, NULL, sessionp);
3005
3006		if (rv != CKR_OK) {
3007			kmf_rv = KMF_ERR_UNINITIALIZED;
3008		}
3009	} else {
3010		kmf_rv = KMF_ERR_UNINITIALIZED;
3011	}
3012
3013out:
3014	if (pSlotList != NULL)
3015		free(pSlotList);
3016	return (kmf_rv);
3017
3018}
3019static KMF_RETURN
3020verify_data(KMF_HANDLE_T handle,
3021	KMF_ALGORITHM_INDEX AlgorithmId,
3022	KMF_X509_SPKI *keyp,
3023	KMF_DATA *data,
3024	KMF_DATA *signed_data)
3025{
3026	KMF_RETURN ret;
3027	PKCS_ALGORITHM_MAP *pAlgMap = NULL;
3028	CK_RV ckRv;
3029	CK_MECHANISM ckMechanism;
3030	CK_OBJECT_HANDLE ckKeyHandle;
3031	KMF_BOOL	bTempKey;
3032	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3033	CK_SESSION_HANDLE	ckSession = NULL;
3034
3035	if (AlgorithmId == KMF_ALGID_NONE)
3036		return (KMF_ERR_BAD_ALGORITHM);
3037
3038	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
3039		AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
3040
3041	if (!pAlgMap)
3042		return (KMF_ERR_BAD_ALGORITHM);
3043
3044	ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
3045		CKF_VERIFY);
3046	if (ret != KMF_OK)
3047		return (ret);
3048
3049	/* Fetch the verifying key */
3050	ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
3051		pAlgMap->key_type, &ckKeyHandle, &bTempKey);
3052
3053	if (ret != KMF_OK) {
3054		return (ret);
3055	}
3056
3057	ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
3058	ckMechanism.pParameter = NULL;
3059	ckMechanism.ulParameterLen = 0;
3060
3061	ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
3062	if (ckRv != CKR_OK) {
3063		if (bTempKey)
3064			(void) C_DestroyObject(ckSession, ckKeyHandle);
3065		SET_ERROR(kmfh, ckRv);
3066		ret = KMF_ERR_INTERNAL;
3067		goto cleanup;
3068	}
3069
3070	ckRv = C_Verify(ckSession,
3071		(CK_BYTE *)data->Data,
3072			(CK_ULONG)data->Length,
3073			(CK_BYTE *)signed_data->Data,
3074			(CK_ULONG)signed_data->Length);
3075
3076	if (ckRv != CKR_OK) {
3077		SET_ERROR(kmfh, ckRv);
3078		ret = KMF_ERR_INTERNAL;
3079	}
3080
3081cleanup:
3082	if (bTempKey)
3083		(void) C_DestroyObject(ckSession, ckKeyHandle);
3084
3085	(void) C_CloseSession(ckSession);
3086
3087	return (ret);
3088}
3089
3090KMF_RETURN
3091KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle,
3092	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
3093	KMF_DATA *insig, KMF_DATA *SignerCertData)
3094{
3095	KMF_RETURN ret = KMF_OK;
3096	KMF_X509_CERTIFICATE *SignerCert = NULL;
3097	KMF_X509_SPKI *pubkey;
3098
3099	if (handle == NULL || indata == NULL ||
3100	    indata->Data == NULL || indata->Length == 0 ||
3101	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
3102	    SignerCertData == NULL || SignerCertData->Data == NULL ||
3103	    SignerCertData->Length == 0)
3104		return (KMF_ERR_BAD_PARAMETER);
3105
3106	/* Decode the signer cert so we can get the SPKI data */
3107	ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
3108	if (ret != KMF_OK)
3109		goto cleanup;
3110
3111	/* Get the public key info from the signer certificate */
3112	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
3113
3114	/* If no algorithm specified, use the certs signature algorithm */
3115	if (algid == KMF_ALGID_NONE) {
3116		algid = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert));
3117	}
3118
3119	if (algid == KMF_ALGID_NONE) {
3120		ret = KMF_ERR_BAD_ALGORITHM;
3121	} else {
3122		ret = verify_data(handle, algid, pubkey, indata, insig);
3123	}
3124
3125cleanup:
3126	if (SignerCert) {
3127		KMF_FreeSignedCert(SignerCert);
3128		free(SignerCert);
3129	}
3130
3131	return (ret);
3132}
3133