pkcs11_spi.c revision 11973:480f5412d630
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 2010 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#include <stdio.h> /* debugging only */
29#include <errno.h>
30#include <values.h>
31
32#include <kmfapiP.h>
33#include <ber_der.h>
34#include <fcntl.h>
35#include <sha1.h>
36#include <bignum.h>
37
38#include <cryptoutil.h>
39#include <security/cryptoki.h>
40#include <security/pkcs11.h>
41
42#define	DEV_RANDOM	"/dev/random"
43
44#define	SETATTR(t, n, atype, value, size) \
45	t[n].type = atype; \
46	t[n].pValue = (CK_BYTE *)value; \
47	t[n].ulValueLen = (CK_ULONG)size;
48
49#define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; \
50	h->lasterr.errcode = c;
51
52typedef struct _objlist {
53	CK_OBJECT_HANDLE handle;
54	struct _objlist *next;
55} OBJLIST;
56
57static KMF_RETURN
58search_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
59	boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
60
61static CK_RV
62getObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
63
64static KMF_RETURN
65keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
66
67static KMF_RETURN
68create_generic_secret_key(KMF_HANDLE_T,
69	int, KMF_ATTRIBUTE *, CK_OBJECT_HANDLE *);
70
71KMF_RETURN
72KMFPK11_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
73
74KMF_RETURN
75KMFPK11_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
76
77void
78KMFPK11_FreeKMFCert(KMF_HANDLE_T,
79	KMF_X509_DER_CERT *kmf_cert);
80
81KMF_RETURN
82KMFPK11_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
83
84KMF_RETURN
85KMFPK11_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
86
87KMF_RETURN
88KMFPK11_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
89
90KMF_RETURN
91KMFPK11_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
92
93KMF_RETURN
94KMFPK11_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
95
96KMF_RETURN
97KMFPK11_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
98
99KMF_RETURN
100KMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
101
102KMF_RETURN
103KMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
104	KMF_DATA *, KMF_DATA *);
105
106KMF_RETURN
107KMFPK11_GetErrorString(KMF_HANDLE_T, char **);
108
109KMF_RETURN
110KMFPK11_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
111
112KMF_RETURN
113KMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
114	KMF_DATA *, KMF_DATA *);
115
116KMF_RETURN
117KMFPK11_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
118
119KMF_RETURN
120KMFPK11_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
121
122KMF_RETURN
123KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
124
125KMF_RETURN
126KMFPK11_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
127
128KMF_RETURN
129KMFPK11_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
130
131
132static
133KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
134{
135	1,			/* Version */
136	KMFPK11_ConfigureKeystore,
137	KMFPK11_FindCert,
138	KMFPK11_FreeKMFCert,
139	KMFPK11_StoreCert,
140	KMFPK11_ImportCert,
141	NULL,			/* ImportCRL */
142	KMFPK11_DeleteCert,
143	NULL,			/* DeleteCRL */
144	KMFPK11_CreateKeypair,
145	KMFPK11_FindKey,
146	KMFPK11_EncodePubKeyData,
147	KMFPK11_SignData,
148	KMFPK11_DeleteKey,
149	NULL,			/* ListCRL */
150	NULL,			/* FindCRL */
151	NULL,			/* FindCertInCRL */
152	KMFPK11_GetErrorString,
153	KMFPK11_FindPrikeyByCert,
154	KMFPK11_DecryptData,
155	KMFPK11_ExportPK12,
156	KMFPK11_CreateSymKey,
157	KMFPK11_GetSymKeyValue,
158	KMFPK11_SetTokenPin,
159	KMFPK11_StoreKey,
160	NULL			/* Finalize */
161};
162
163KMF_PLUGIN_FUNCLIST *
164KMF_Plugin_Initialize()
165{
166	return (&pk11token_plugin_table);
167}
168
169KMF_RETURN
170KMFPK11_ConfigureKeystore(KMF_HANDLE_T handle,
171	int numattr, KMF_ATTRIBUTE *attrlist)
172{
173	KMF_RETURN rv = KMF_OK;
174	char *label;
175	boolean_t readonly = B_TRUE;
176
177	label = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
178	if (label == NULL) {
179		return (KMF_ERR_BAD_PARAMETER);
180	}
181
182	/* "readonly" is optional. Default is TRUE */
183	(void) kmf_get_attr(KMF_READONLY_ATTR, attrlist, numattr,
184	    (void *)&readonly, NULL);
185
186	rv = kmf_select_token(handle, label, readonly);
187
188	return (rv);
189}
190
191static KMF_RETURN
192pk11_authenticate(KMF_HANDLE_T handle,
193	KMF_CREDENTIAL *cred)
194{
195
196	CK_RV ck_rv = CKR_OK;
197	CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
198
199	if (hSession == NULL)
200		return (KMF_ERR_NO_TOKEN_SELECTED);
201
202	if (cred == NULL || cred->cred == NULL) {
203		return (KMF_ERR_BAD_PARAMETER);
204	}
205
206	if ((ck_rv = C_Login(hSession, CKU_USER, (uchar_t *)cred->cred,
207	    cred->credlen)) != CKR_OK) {
208		if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
209			handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
210			handle->lasterr.errcode = ck_rv;
211			return (KMF_ERR_AUTH_FAILED);
212		}
213	}
214
215	return (KMF_OK);
216}
217
218static KMF_RETURN
219PK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
220		KMF_X509_DER_CERT *kmfcert)
221{
222	KMF_RETURN rv = 0;
223	CK_RV ckrv = CKR_OK;
224
225	CK_CERTIFICATE_TYPE cktype;
226	CK_OBJECT_CLASS	class;
227	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
228	CK_BYTE *subject = NULL, *value = NULL;
229	char *label = NULL;
230	CK_ATTRIBUTE templ[10];
231
232	(void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
233	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
234
235	/*  Is this a certificate object ? */
236	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
237	if (ckrv != CKR_OK || class != CKO_CERTIFICATE)  {
238		SET_ERROR(kmfh, ckrv);
239		return (KMF_ERR_INTERNAL);
240	}
241
242	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
243	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
244
245	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
246		SET_ERROR(kmfh, ckrv);
247		return (ckrv);
248	} else {
249		int i = 0;
250		/* What attributes are available and how big are they? */
251		subject_len = issuer_len = serno_len = id_len = value_len = 0;
252
253		SETATTR(templ, i, CKA_SUBJECT,	NULL, subject_len);
254		i++;
255		SETATTR(templ, i, CKA_ISSUER,	NULL, issuer_len);
256		i++;
257		SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
258		i++;
259		SETATTR(templ, i, CKA_ID, NULL, id_len);
260		i++;
261		SETATTR(templ, i, CKA_VALUE, NULL, value_len);
262		i++;
263
264		/*
265		 * Query the object with NULL values in the pValue spot
266		 * so we know how much space to allocate for each field.
267		 */
268		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
269		if (ckrv != CKR_OK)  {
270			SET_ERROR(kmfh, ckrv);
271			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
272		}
273
274		subject_len	= templ[0].ulValueLen;
275		issuer_len	= templ[1].ulValueLen;
276		serno_len	= templ[2].ulValueLen;
277		id_len		= templ[3].ulValueLen;
278		value_len	= templ[4].ulValueLen;
279
280		/*
281		 * For PKCS#11 CKC_X_509 certificate objects,
282		 * the following attributes must be defined.
283		 * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
284		 * CKA_VALUE.
285		 */
286		if (subject_len == 0 || issuer_len == 0 ||
287		    serno_len == 0 || value_len == 0) {
288			return (KMF_ERR_INTERNAL);
289		}
290
291		/* Only fetch the value field if we are saving the data */
292		if (kmfcert != NULL) {
293			int i = 0;
294			value = malloc(value_len);
295			if (value == NULL) {
296				rv = KMF_ERR_MEMORY;
297				goto errout;
298			}
299
300			SETATTR(templ, i, CKA_VALUE, value, value_len);
301			i++;
302
303			/* re-query the object with room for the value attr */
304			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
305			    templ, i);
306
307			if (ckrv != CKR_OK)  {
308				SET_ERROR(kmfh, ckrv);
309				rv = KMF_ERR_INTERNAL;
310				goto errout;
311			}
312
313			kmfcert->certificate.Data = value;
314			kmfcert->certificate.Length = value_len;
315			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
316			kmfcert->kmf_private.keystore_type =
317			    KMF_KEYSTORE_PK11TOKEN;
318
319			ckrv = getObjectLabel(kmfh, hObj, &label);
320			if (ckrv == CKR_OK && label != NULL) {
321				kmfcert->kmf_private.label = (char *)label;
322			}
323
324			rv = KMF_OK;
325		}
326	}
327
328errout:
329	if (rv != KMF_OK) {
330		if (subject)
331			free(subject);
332		if (value)
333			free(value);
334
335		if (kmfcert) {
336			kmfcert->certificate.Data = NULL;
337			kmfcert->certificate.Length = 0;
338		}
339	}
340	return (rv);
341}
342
343static void
344free_objlist(OBJLIST *head)
345{
346	OBJLIST *temp = head;
347
348	while (temp != NULL) {
349		head = head->next;
350		free(temp);
351		temp = head;
352	}
353}
354
355/*
356 * The caller should make sure that the templ->pValue is NULL since
357 * it will be overwritten below.
358 */
359static KMF_RETURN
360get_attr(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
361	CK_ATTRIBUTE *templ)
362{
363	CK_RV rv;
364
365	rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
366	if (rv != CKR_OK) {
367		SET_ERROR(kmfh, rv);
368		return (KMF_ERR_INTERNAL);
369	}
370
371	if (templ->ulValueLen > 0) {
372		templ->pValue = malloc(templ->ulValueLen);
373		if (templ->pValue == NULL)
374			return (KMF_ERR_MEMORY);
375
376		rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
377		if (rv != CKR_OK) {
378			SET_ERROR(kmfh, rv);
379			return (KMF_ERR_INTERNAL);
380		}
381	}
382
383	return (KMF_OK);
384}
385
386/*
387 * Match a certificate with an issuer and/or subject name.
388 * This is tricky because we cannot reliably compare DER encodings
389 * because RDNs may have their AV-pairs in different orders even
390 * if the values are the same.  You must compare individual
391 * AV pairs for the RDNs.
392 *
393 * RETURN: 0 for a match, non-zero for a non-match.
394 */
395static KMF_RETURN
396matchcert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
397	KMF_X509_NAME *issuer, KMF_X509_NAME *subject)
398{
399	KMF_RETURN rv = KMF_OK;
400	CK_ATTRIBUTE certattr;
401	KMF_DATA name;
402	KMF_X509_NAME dn;
403
404	if (issuer->numberOfRDNs > 0) {
405		certattr.type = CKA_ISSUER;
406		certattr.pValue = NULL;
407		certattr.ulValueLen = 0;
408
409		rv = get_attr(kmfh, obj, &certattr);
410
411		if (rv == KMF_OK) {
412			name.Data = certattr.pValue;
413			name.Length = certattr.ulValueLen;
414			rv = DerDecodeName(&name, &dn);
415			if (rv == KMF_OK) {
416				rv = kmf_compare_rdns(issuer, &dn);
417				kmf_free_dn(&dn);
418			}
419			free(certattr.pValue);
420		}
421
422		if (rv != KMF_OK)
423			return (rv);
424	}
425	if (subject->numberOfRDNs > 0) {
426		certattr.type = CKA_SUBJECT;
427		certattr.pValue = NULL;
428		certattr.ulValueLen = 0;
429
430		rv = get_attr(kmfh, obj, &certattr);
431
432		if (rv == KMF_OK) {
433			name.Data = certattr.pValue;
434			name.Length = certattr.ulValueLen;
435			rv = DerDecodeName(&name, &dn);
436			if (rv == KMF_OK) {
437				rv = kmf_compare_rdns(subject, &dn);
438				kmf_free_dn(&dn);
439			}
440			free(certattr.pValue);
441		}
442	}
443
444	return (rv);
445}
446
447/*
448 * delete "curr" node from the "newlist".
449 */
450static void
451pk11_delete_obj_from_list(OBJLIST **newlist,
452	OBJLIST **prev, OBJLIST **curr)
453{
454
455	if (*curr == *newlist) {
456		/* first node in the list */
457		*newlist = (*curr)->next;
458		*prev = (*curr)->next;
459		free(*curr);
460		*curr = *newlist;
461	} else {
462		(*prev)->next = (*curr)->next;
463		free(*curr);
464		*curr = (*prev)->next;
465	}
466}
467
468/*
469 * search_certs
470 *
471 * Because this code is shared by the FindCert and
472 * DeleteCert functions, put it in a separate routine
473 * to save some work and make code easier to debug and
474 * read.
475 */
476static KMF_RETURN
477search_certs(KMF_HANDLE_T handle,
478	char *label, char *issuer, char *subject, KMF_BIGINT *serial,
479	boolean_t private, KMF_CERT_VALIDITY validity,
480	OBJLIST **objlist, uint32_t *numobj)
481{
482	KMF_RETURN rv = KMF_OK;
483	CK_RV ckrv = CKR_OK;
484	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
485	CK_ATTRIBUTE templ[10];
486	CK_BBOOL true = TRUE;
487	CK_OBJECT_CLASS	oclass = CKO_CERTIFICATE;
488	CK_CERTIFICATE_TYPE ctype = CKC_X_509;
489	KMF_X509_NAME subjectDN, issuerDN;
490	int i;
491	OBJLIST *newlist, *tail;
492	CK_ULONG num = 0;
493	uint32_t num_ok_certs = 0; /* number of non-expired or expired certs */
494
495	(void) memset(&templ, 0, 10 * sizeof (CK_ATTRIBUTE));
496	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
497	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
498	i = 0;
499	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
500	SETATTR(templ, i, CKA_CLASS, &oclass, sizeof (oclass)); i++;
501	SETATTR(templ, i, CKA_CERTIFICATE_TYPE, &ctype,	sizeof (ctype)); i++;
502
503	if (label != NULL && strlen(label)) {
504		SETATTR(templ, i, CKA_LABEL, label, strlen(label));
505		i++;
506	}
507	if (private) {
508		SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true)); i++;
509	}
510
511	if (issuer != NULL && strlen(issuer)) {
512		if ((rv = kmf_dn_parser(issuer, &issuerDN)) != KMF_OK)
513			return (rv);
514	}
515	if (subject != NULL && strlen(subject)) {
516		if ((rv = kmf_dn_parser(subject, &subjectDN)) != KMF_OK)
517			return (rv);
518	}
519
520	if (serial != NULL && serial->val != NULL && serial->len > 0) {
521		SETATTR(templ, i, CKA_SERIAL_NUMBER, serial->val, serial->len);
522		i++;
523	}
524
525	(*numobj) = 0;
526	*objlist = NULL;
527	newlist = NULL;
528
529	ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, i);
530	if (ckrv != CKR_OK)
531		goto cleanup;
532
533	tail = newlist = NULL;
534	while (ckrv == CKR_OK) {
535		CK_OBJECT_HANDLE tObj;
536		ckrv = C_FindObjects(kmfh->pk11handle, &tObj, 1, &num);
537		if (ckrv != CKR_OK || num == 0)
538			break;
539
540		/*
541		 * 'matchcert' returns 0 if subject/issuer match
542		 *
543		 * If no match, move on to the next one
544		 */
545		if (matchcert(kmfh, tObj, &issuerDN, &subjectDN))
546			continue;
547
548		if (newlist == NULL) {
549			newlist = malloc(sizeof (OBJLIST));
550			if (newlist == NULL) {
551				rv = KMF_ERR_MEMORY;
552				break;
553			}
554			newlist->handle = tObj;
555			newlist->next = NULL;
556			tail = newlist;
557		} else {
558			tail->next = malloc(sizeof (OBJLIST));
559			if (tail->next != NULL) {
560				tail = tail->next;
561			} else {
562				rv = KMF_ERR_MEMORY;
563				break;
564			}
565			tail->handle = tObj;
566			tail->next = NULL;
567		}
568		(*numobj)++;
569	}
570	ckrv = C_FindObjectsFinal(kmfh->pk11handle);
571
572cleanup:
573	if (ckrv != CKR_OK) {
574		SET_ERROR(kmfh, ckrv);
575		rv = KMF_ERR_INTERNAL;
576		if (newlist != NULL) {
577			free_objlist(newlist);
578			*numobj = 0;
579			newlist = NULL;
580		}
581	} else {
582		if (validity == KMF_ALL_CERTS) {
583			*objlist = newlist;
584		} else {
585			OBJLIST *node, *prev;
586			KMF_X509_DER_CERT  tmp_kmf_cert;
587			uint32_t i = 0;
588
589			node = prev = newlist;
590			/*
591			 * Now check to see if any found certificate is expired
592			 * or valid.
593			 */
594			while (node != NULL && i < (*numobj)) {
595				(void) memset(&tmp_kmf_cert, 0,
596				    sizeof (KMF_X509_DER_CERT));
597				rv = PK11Cert2KMFCert(kmfh, node->handle,
598				    &tmp_kmf_cert);
599				if (rv != KMF_OK) {
600					goto cleanup1;
601				}
602
603				rv = kmf_check_cert_date(handle,
604				    &tmp_kmf_cert.certificate);
605
606				if (validity == KMF_NONEXPIRED_CERTS) {
607					if (rv == KMF_OK)  {
608						num_ok_certs++;
609						prev = node;
610						node = node->next;
611					} else if (rv ==
612					    KMF_ERR_VALIDITY_PERIOD) {
613						/*
614						 * expired - remove it from list
615						 */
616						pk11_delete_obj_from_list(
617						    &newlist, &prev, &node);
618					} else {
619						goto cleanup1;
620					}
621				}
622
623				if (validity == KMF_EXPIRED_CERTS) {
624					if (rv == KMF_ERR_VALIDITY_PERIOD)  {
625						num_ok_certs++;
626						prev = node;
627						node = node->next;
628						rv = KMF_OK;
629					} else if (rv == KMF_OK) {
630						/*
631						 * valid - remove it from list
632						 */
633						pk11_delete_obj_from_list(
634						    &newlist, &prev, &node);
635					} else {
636						goto cleanup1;
637					}
638				}
639				i++;
640				kmf_free_kmf_cert(handle, &tmp_kmf_cert);
641			}
642			*numobj = num_ok_certs;
643			*objlist = newlist;
644		}
645	}
646
647cleanup1:
648	if (rv != KMF_OK && newlist != NULL) {
649		free_objlist(newlist);
650		*numobj = 0;
651		*objlist = NULL;
652	}
653
654	if (issuer != NULL)
655		kmf_free_dn(&issuerDN);
656
657	if (subject != NULL)
658		kmf_free_dn(&subjectDN);
659
660	return (rv);
661}
662
663/*
664 * The caller may pass a NULL value for kmf_cert below and the function will
665 * just return the number of certs found (in num_certs).
666 */
667KMF_RETURN
668KMFPK11_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
669{
670	KMF_RETURN rv = 0;
671	uint32_t want_certs;
672	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
673	OBJLIST *objlist = NULL;
674	uint32_t *num_certs;
675	KMF_X509_DER_CERT *kmf_cert = NULL;
676	char *certlabel = NULL;
677	char *issuer = NULL;
678	char *subject = NULL;
679	KMF_BIGINT *serial = NULL;
680	KMF_CERT_VALIDITY validity;
681	KMF_CREDENTIAL *cred = NULL;
682	boolean_t private;
683
684	if (kmfh == NULL)
685		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
686
687	if (kmfh->pk11handle == CK_INVALID_HANDLE)
688		return (KMF_ERR_NO_TOKEN_SELECTED);
689
690	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
691	if (num_certs == NULL)
692		return (KMF_ERR_BAD_PARAMETER);
693
694	if (*num_certs > 0)
695		want_certs = *num_certs;
696	else
697		want_certs = MAXINT; /* count them all */
698
699	*num_certs = 0;
700
701	/* Get the optional returned certificate list */
702	kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
703	    numattr);
704
705	/* Get optional search criteria attributes */
706	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
707	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
708	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
709	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
710
711	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
712	    &validity, NULL);
713	if (rv != KMF_OK) {
714		validity = KMF_ALL_CERTS;
715		rv = KMF_OK;
716	}
717
718	rv = kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
719	    (void *)&private, NULL);
720	if (rv != KMF_OK) {
721		private = B_FALSE;
722		rv = KMF_OK;
723	}
724
725	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
726	if (cred != NULL) {
727		rv = pk11_authenticate(handle, cred);
728		if (rv != KMF_OK)
729			return (rv);
730	}
731
732	/* Start searching */
733	rv = search_certs(handle, certlabel, issuer, subject, serial, private,
734	    validity, &objlist, num_certs);
735
736	if (rv == KMF_OK && objlist != NULL && kmf_cert != NULL) {
737		OBJLIST *node = objlist;
738		int i = 0;
739		while (node != NULL && i < want_certs) {
740			rv = PK11Cert2KMFCert(kmfh, node->handle,
741			    &kmf_cert[i]);
742			i++;
743			node = node->next;
744		}
745	}
746
747	if (objlist != NULL)
748		free_objlist(objlist);
749
750	if (*num_certs == 0)
751		rv = KMF_ERR_CERT_NOT_FOUND;
752
753	return (rv);
754}
755
756/*ARGSUSED*/
757void
758KMFPK11_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
759{
760	if (kmf_cert != NULL && kmf_cert->certificate.Data != NULL) {
761		free(kmf_cert->certificate.Data);
762		kmf_cert->certificate.Data = NULL;
763		kmf_cert->certificate.Length = 0;
764
765		if (kmf_cert->kmf_private.label != NULL) {
766			free(kmf_cert->kmf_private.label);
767			kmf_cert->kmf_private.label = NULL;
768		}
769	}
770}
771
772KMF_RETURN
773KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
774	KMF_DATA *eData)
775{
776	KMF_RETURN ret = KMF_OK;
777	CK_RV rv;
778	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
779	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
780	CK_KEY_TYPE ckKeyType;
781	KMF_DATA Modulus, Exponent, Prime, Subprime, Base, Value;
782	KMF_OID *Algorithm;
783	BerElement *asn1 = NULL;
784	BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
785	KMF_X509_SPKI spki;
786	CK_BYTE ec_params[256], ec_point[256];
787
788	CK_ATTRIBUTE rsaTemplate[4];
789	CK_ATTRIBUTE dsaTemplate[6];
790	CK_ATTRIBUTE ecdsaTemplate[6];
791
792	if (kmfh == NULL)
793		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
794
795	if (kmfh->pk11handle == CK_INVALID_HANDLE)
796		return (KMF_ERR_NO_TOKEN_SELECTED);
797
798	if (pKey == NULL || pKey->keyp == CK_INVALID_HANDLE)
799		return (KMF_ERR_BAD_PARAMETER);
800
801	(void) memset(&Modulus, 0, sizeof (Modulus));
802	(void) memset(&Exponent, 0, sizeof (Exponent));
803	(void) memset(&Prime, 0, sizeof (Prime));
804	(void) memset(&Subprime, 0, sizeof (Subprime));
805	(void) memset(&Base, 0, sizeof (Base));
806	(void) memset(&Value, 0, sizeof (Value));
807
808	switch (pKey->keyalg) {
809		case KMF_RSA:
810			SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass,
811			    sizeof (ckObjClass));
812			SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
813			    sizeof (ckKeyType));
814			SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
815			    Modulus.Length);
816			SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
817			    Exponent.Data, Exponent.Length);
818			/* Get the length of the fields */
819			rv = C_GetAttributeValue(kmfh->pk11handle,
820			    (CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4);
821			if (rv != CKR_OK) {
822				SET_ERROR(kmfh, rv);
823				return (KMF_ERR_BAD_PARAMETER);
824			}
825
826			Modulus.Length = rsaTemplate[2].ulValueLen;
827			Modulus.Data = malloc(Modulus.Length);
828			if (Modulus.Data == NULL)
829				return (KMF_ERR_MEMORY);
830
831			Exponent.Length = rsaTemplate[3].ulValueLen;
832			Exponent.Data = malloc(Exponent.Length);
833			if (Exponent.Data == NULL) {
834				free(Modulus.Data);
835				return (KMF_ERR_MEMORY);
836			}
837
838			SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
839			    Modulus.Length);
840			SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
841			    Exponent.Data, Exponent.Length);
842			/* Now get the values */
843			rv = C_GetAttributeValue(kmfh->pk11handle,
844			    (CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4);
845			if (rv != CKR_OK) {
846				SET_ERROR(kmfh, rv);
847				free(Modulus.Data);
848				free(Exponent.Data);
849				return (KMF_ERR_BAD_PARAMETER);
850			}
851
852			/*
853			 * This is the KEY algorithm, not the
854			 * signature algorithm.
855			 */
856			Algorithm = x509_algid_to_algoid(KMF_ALGID_RSA);
857			if (Algorithm != NULL) {
858
859				/* Encode the RSA Key Data */
860				if ((asn1 = kmfder_alloc()) == NULL) {
861					free(Modulus.Data);
862					free(Exponent.Data);
863					return (KMF_ERR_MEMORY);
864				}
865				if (kmfber_printf(asn1, "{II}",	Modulus.Data,
866				    Modulus.Length, Exponent.Data,
867				    Exponent.Length) == -1) {
868					kmfber_free(asn1, 1);
869					free(Modulus.Data);
870					free(Exponent.Data);
871					return (KMF_ERR_ENCODING);
872				}
873				if (kmfber_flatten(asn1, &EncodedKey) == -1) {
874					kmfber_free(asn1, 1);
875					free(Modulus.Data);
876					free(Exponent.Data);
877					return (KMF_ERR_ENCODING);
878				}
879				kmfber_free(asn1, 1);
880			}
881
882			free(Exponent.Data);
883			free(Modulus.Data);
884
885			break;
886		case KMF_DSA:
887			SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass,
888			    sizeof (ckObjClass));
889			SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
890			    sizeof (ckKeyType));
891			SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
892			    Prime.Length);
893			SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
894			    Subprime.Length);
895			SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
896			    Base.Length);
897			SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
898			    Value.Length);
899
900			/* Get the length of the fields */
901			rv = C_GetAttributeValue(kmfh->pk11handle,
902			    (CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6);
903			if (rv != CKR_OK) {
904				SET_ERROR(kmfh, rv);
905				return (KMF_ERR_BAD_PARAMETER);
906			}
907			Prime.Length = dsaTemplate[2].ulValueLen;
908			Prime.Data = malloc(Prime.Length);
909			if (Prime.Data == NULL) {
910				return (KMF_ERR_MEMORY);
911			}
912
913			Subprime.Length = dsaTemplate[3].ulValueLen;
914			Subprime.Data = malloc(Subprime.Length);
915			if (Subprime.Data == NULL) {
916				free(Prime.Data);
917				return (KMF_ERR_MEMORY);
918			}
919
920			Base.Length = dsaTemplate[4].ulValueLen;
921			Base.Data = malloc(Base.Length);
922			if (Base.Data == NULL) {
923				free(Prime.Data);
924				free(Subprime.Data);
925				return (KMF_ERR_MEMORY);
926			}
927
928			Value.Length = dsaTemplate[5].ulValueLen;
929			Value.Data = malloc(Value.Length);
930			if (Value.Data == NULL) {
931				free(Prime.Data);
932				free(Subprime.Data);
933				free(Base.Data);
934				return (KMF_ERR_MEMORY);
935			}
936			SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
937			    Prime.Length);
938			SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
939			    Subprime.Length);
940			SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
941			    Base.Length);
942			SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
943			    Value.Length);
944
945			/* Now get the values */
946			rv = C_GetAttributeValue(kmfh->pk11handle,
947			    (CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6);
948			if (rv != CKR_OK) {
949				free(Prime.Data);
950				free(Subprime.Data);
951				free(Base.Data);
952				free(Value.Data);
953				SET_ERROR(kmfh, rv);
954				return (KMF_ERR_BAD_PARAMETER);
955			}
956			/*
957			 * This is the KEY algorithm, not the
958			 * signature algorithm.
959			 */
960			Algorithm = x509_algid_to_algoid(KMF_ALGID_DSA);
961
962			/* Encode the DSA Algorithm Parameters */
963			if ((asn1 = kmfder_alloc()) == NULL) {
964				free(Prime.Data);
965				free(Subprime.Data);
966				free(Base.Data);
967				free(Value.Data);
968				return (KMF_ERR_MEMORY);
969			}
970
971			if (kmfber_printf(asn1, "{III}", Prime.Data,
972			    Prime.Length, Subprime.Data, Subprime.Length,
973			    Base.Data, Base.Length) == -1) {
974
975				kmfber_free(asn1, 1);
976				free(Prime.Data);
977				free(Subprime.Data);
978				free(Base.Data);
979				free(Value.Data);
980				return (KMF_ERR_ENCODING);
981			}
982			if (kmfber_flatten(asn1, &PubKeyParams) == -1) {
983				kmfber_free(asn1, 1);
984				free(Prime.Data);
985				free(Subprime.Data);
986				free(Base.Data);
987				free(Value.Data);
988				return (KMF_ERR_ENCODING);
989			}
990			kmfber_free(asn1, 1);
991			free(Prime.Data);
992			free(Subprime.Data);
993			free(Base.Data);
994
995			/* Encode the DSA Key Value */
996			if ((asn1 = kmfder_alloc()) == NULL) {
997				free(Value.Data);
998				return (KMF_ERR_MEMORY);
999			}
1000
1001			if (kmfber_printf(asn1, "I",
1002			    Value.Data, Value.Length) == -1) {
1003				kmfber_free(asn1, 1);
1004				free(Value.Data);
1005				return (KMF_ERR_ENCODING);
1006			}
1007			if (kmfber_flatten(asn1, &EncodedKey) == -1) {
1008				kmfber_free(asn1, 1);
1009				free(Value.Data);
1010				return (KMF_ERR_ENCODING);
1011			}
1012			kmfber_free(asn1, 1);
1013			free(Value.Data);
1014			break;
1015		case KMF_ECDSA:
1016			/* The EC_PARAMS are the PubKey algorithm parameters */
1017			PubKeyParams = calloc(1, sizeof (BerValue));
1018			if (PubKeyParams == NULL)
1019				return (KMF_ERR_MEMORY);
1020			EncodedKey = calloc(1, sizeof (BerValue));
1021			if (EncodedKey == NULL) {
1022				free(PubKeyParams);
1023				return (KMF_ERR_MEMORY);
1024			}
1025			SETATTR(ecdsaTemplate, 0, CKA_EC_PARAMS,
1026			    &ec_params, sizeof (ec_params));
1027			SETATTR(ecdsaTemplate, 1, CKA_EC_POINT,
1028			    &ec_point, sizeof (ec_point));
1029
1030			/* Get the length of the fields */
1031			rv = C_GetAttributeValue(kmfh->pk11handle,
1032			    (CK_OBJECT_HANDLE)pKey->keyp,
1033			    ecdsaTemplate, 2);
1034			if (rv != CKR_OK) {
1035				SET_ERROR(kmfh, rv);
1036				return (KMF_ERR_BAD_PARAMETER);
1037			}
1038			/* The params are to be used as algorithm parameters */
1039			PubKeyParams->bv_val = (char *)ec_params;
1040			PubKeyParams->bv_len = ecdsaTemplate[0].ulValueLen;
1041			/*
1042			 * The EC_POINT is to be used as the subject pub key.
1043			 */
1044			EncodedKey->bv_val = (char *)ec_point;
1045			EncodedKey->bv_len = ecdsaTemplate[1].ulValueLen;
1046
1047			/* Use the EC_PUBLIC_KEY OID */
1048			Algorithm = (KMF_OID *)&KMFOID_EC_PUBLIC_KEY;
1049			break;
1050		default:
1051			return (KMF_ERR_BAD_PARAMETER);
1052	}
1053
1054	/* Now, build an SPKI structure for the final encoding step */
1055	spki.algorithm.algorithm = *Algorithm;
1056	if (PubKeyParams != NULL) {
1057		spki.algorithm.parameters.Data =
1058		    (uchar_t *)PubKeyParams->bv_val;
1059		spki.algorithm.parameters.Length = PubKeyParams->bv_len;
1060	} else {
1061		spki.algorithm.parameters.Data = NULL;
1062		spki.algorithm.parameters.Length = 0;
1063	}
1064
1065	if (EncodedKey != NULL) {
1066		spki.subjectPublicKey.Data = (uchar_t *)EncodedKey->bv_val;
1067		spki.subjectPublicKey.Length = EncodedKey->bv_len;
1068	} else {
1069		spki.subjectPublicKey.Data = NULL;
1070		spki.subjectPublicKey.Length = 0;
1071	}
1072
1073	/* Finally, encode the entire SPKI record */
1074	ret = DerEncodeSPKI(&spki, eData);
1075
1076cleanup:
1077	if (EncodedKey) {
1078		if (pKey->keyalg != KMF_ECDSA)
1079			free(EncodedKey->bv_val);
1080		free(EncodedKey);
1081	}
1082
1083	if (PubKeyParams) {
1084		if (pKey->keyalg != KMF_ECDSA)
1085			free(PubKeyParams->bv_val);
1086		free(PubKeyParams);
1087	}
1088
1089	return (ret);
1090}
1091
1092static KMF_RETURN
1093CreateCertObject(KMF_HANDLE_T handle, char *label, KMF_DATA *pcert)
1094{
1095	KMF_RETURN rv = 0;
1096	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1097
1098	KMF_X509_CERTIFICATE *signed_cert_ptr = NULL;
1099	KMF_DATA data;
1100	KMF_DATA Id;
1101
1102	CK_RV ckrv;
1103	CK_ULONG subject_len, issuer_len, serno_len;
1104	CK_BYTE *subject, *issuer, *serial, nullserno;
1105	CK_BBOOL true = TRUE;
1106	CK_CERTIFICATE_TYPE certtype = CKC_X_509;
1107	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1108	CK_ATTRIBUTE x509templ[11];
1109	CK_OBJECT_HANDLE hCert = NULL;
1110	int i;
1111
1112	if (kmfh == NULL)
1113		return (KMF_ERR_INTERNAL); /* should not happen */
1114
1115	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1116		return (KMF_ERR_INTERNAL); /* should not happen */
1117
1118	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1119		return (KMF_ERR_INTERNAL);  /* should not happen */
1120
1121	/*
1122	 * The data *must* be a DER encoded X.509 certificate.
1123	 * Convert it to a CSSM cert and then parse the fields so
1124	 * the PKCS#11 attributes can be filled in correctly.
1125	 */
1126	rv = DerDecodeSignedCertificate((const KMF_DATA *)pcert,
1127	    &signed_cert_ptr);
1128	if (rv != KMF_OK) {
1129		return (KMF_ERR_ENCODING);
1130	}
1131
1132	/*
1133	 * Encode fields into PKCS#11 attributes.
1134	 */
1135
1136	/* Get the subject name */
1137	rv = DerEncodeName(&signed_cert_ptr->certificate.subject, &data);
1138	if (rv == KMF_OK) {
1139		subject = data.Data;
1140		subject_len = data.Length;
1141	} else {
1142		rv = KMF_ERR_ENCODING;
1143		goto cleanup;
1144	}
1145
1146	/* Encode the issuer */
1147	rv = DerEncodeName(&signed_cert_ptr->certificate.issuer, &data);
1148	if (rv == KMF_OK) {
1149		issuer = data.Data;
1150		issuer_len = data.Length;
1151	} else {
1152		rv = KMF_ERR_ENCODING;
1153		goto cleanup;
1154	}
1155
1156	/* Encode serial number */
1157	if (signed_cert_ptr->certificate.serialNumber.len > 0 &&
1158	    signed_cert_ptr->certificate.serialNumber.val != NULL) {
1159		serial = signed_cert_ptr->certificate.serialNumber.val;
1160		serno_len = signed_cert_ptr->certificate.serialNumber.len;
1161	} else {
1162		/*
1163		 * RFC3280 says to gracefully handle certs with serial numbers
1164		 * of 0.
1165		 */
1166		nullserno = '\0';
1167		serial  = &nullserno;
1168		serno_len = 1;
1169	}
1170
1171	/* Generate an ID from the SPKI data */
1172	rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
1173	    &Id);
1174
1175	if (rv != KMF_OK) {
1176		goto cleanup;
1177	}
1178
1179	i = 0;
1180	SETATTR(x509templ, i, CKA_CLASS, &certClass, sizeof (certClass)); i++;
1181	SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
1182	    sizeof (certtype));
1183	i++;
1184	SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
1185	SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
1186	SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
1187	SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
1188	SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
1189	SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
1190	if (label != NULL && strlen(label)) {
1191		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));	i++;
1192	}
1193	/*
1194	 * The cert object handle is actually "leaked" here.  If the app
1195	 * really wants to clean up the data space, it will have to call
1196	 * KMF_DeleteCert and specify the softtoken keystore.
1197	 */
1198	ckrv = C_CreateObject(kmfh->pk11handle, x509templ, i, &hCert);
1199	if (ckrv != CKR_OK) {
1200		/* Report authentication failures to the caller */
1201		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
1202		    ckrv == CKR_PIN_INCORRECT ||
1203		    ckrv == CKR_PIN_INVALID ||
1204		    ckrv == CKR_PIN_EXPIRED ||
1205		    ckrv == CKR_PIN_LOCKED ||
1206		    ckrv == CKR_SESSION_READ_ONLY)
1207			rv = KMF_ERR_AUTH_FAILED;
1208		else
1209			rv = KMF_ERR_INTERNAL;
1210		SET_ERROR(kmfh, ckrv);
1211	}
1212	free(subject);
1213	free(issuer);
1214
1215cleanup:
1216	if (Id.Data != NULL)
1217		free(Id.Data);
1218
1219	if (signed_cert_ptr) {
1220		kmf_free_signed_cert(signed_cert_ptr);
1221		free(signed_cert_ptr);
1222	}
1223	return (rv);
1224}
1225
1226
1227KMF_RETURN
1228KMFPK11_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1229{
1230	KMF_RETURN rv = 0;
1231	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1232	KMF_DATA *cert = NULL;
1233	KMF_CREDENTIAL *cred = NULL;
1234	char *label = NULL;
1235
1236	if (kmfh == NULL)
1237		return (KMF_ERR_UNINITIALIZED);
1238
1239	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1240		return (KMF_ERR_NO_TOKEN_SELECTED);
1241
1242	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1243	if (cert == NULL || cert->Data == NULL || cert->Length == 0)
1244		return (KMF_ERR_BAD_PARAMETER);
1245
1246	/* label attribute is optional */
1247	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1248
1249	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1250	if (cred != NULL) {
1251		rv = pk11_authenticate(handle, cred);
1252		if (rv != KMF_OK)
1253			return (rv);
1254	}
1255
1256	rv = CreateCertObject(handle, label, cert);
1257	return (rv);
1258}
1259
1260KMF_RETURN
1261KMFPK11_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1262{
1263	KMF_RETURN rv = 0;
1264	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1265	char *certfile = NULL;
1266	char *label = NULL;
1267	KMF_ENCODE_FORMAT format;
1268	KMF_CREDENTIAL *cred = NULL;
1269	KMF_DATA  cert1 = { NULL, 0};
1270	KMF_DATA  cert2 = { NULL, 0};
1271
1272	if (kmfh == NULL)
1273		return (KMF_ERR_UNINITIALIZED);
1274
1275	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1276		return (KMF_ERR_NO_TOKEN_SELECTED);
1277
1278	/*
1279	 * Get the input cert filename attribute, check if it is a valid
1280	 * certificate and auto-detect the file format of it.
1281	 */
1282	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
1283	if (certfile == NULL)
1284		return (KMF_ERR_BAD_PARAMETER);
1285
1286	rv = kmf_is_cert_file(handle, certfile, &format);
1287	if (rv != KMF_OK)
1288		return (rv);
1289
1290	/* Read in the CERT file */
1291	rv = kmf_read_input_file(handle, certfile, &cert1);
1292	if (rv != KMF_OK) {
1293		return (rv);
1294	}
1295
1296	/* The label attribute is optional */
1297	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1298
1299	/*
1300	 * If the input certificate is in PEM format, we need to convert
1301	 * it to DER first.
1302	 */
1303	if (format == KMF_FORMAT_PEM) {
1304		int derlen;
1305		rv = kmf_pem_to_der(cert1.Data, cert1.Length,
1306		    &cert2.Data, &derlen);
1307		if (rv != KMF_OK) {
1308			goto out;
1309		}
1310		cert2.Length = (size_t)derlen;
1311	}
1312
1313	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1314	if (cred != NULL) {
1315		rv = pk11_authenticate(handle, cred);
1316		if (rv != KMF_OK)
1317			return (rv);
1318	}
1319
1320	rv = CreateCertObject(handle, label,
1321	    format == KMF_FORMAT_ASN1 ? &cert1 : &cert2);
1322
1323out:
1324	if (cert1.Data != NULL) {
1325		free(cert1.Data);
1326	}
1327
1328	if (cert2.Data != NULL) {
1329		free(cert2.Data);
1330	}
1331
1332	return (rv);
1333}
1334
1335KMF_RETURN
1336KMFPK11_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1337{
1338	KMF_RETURN rv = 0;
1339	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1340	OBJLIST *objlist;
1341	uint32_t numObjects = 0;
1342	char *certlabel = NULL;
1343	char *issuer = NULL;
1344	char *subject = NULL;
1345	KMF_BIGINT *serial = NULL;
1346	KMF_CERT_VALIDITY validity;
1347	boolean_t private;
1348
1349	if (kmfh == NULL)
1350		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1351
1352	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1353		return (KMF_ERR_NO_TOKEN_SELECTED);
1354
1355
1356	/* Get the search criteria attributes. They are all optional. */
1357	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1358	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1359	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1360	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1361
1362	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1363	    &validity, NULL);
1364	if (rv != KMF_OK) {
1365		validity = KMF_ALL_CERTS;
1366		rv = KMF_OK;
1367	}
1368
1369	rv = kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
1370	    (void *)&private, NULL);
1371	if (rv != KMF_OK) {
1372		private = B_FALSE;
1373		rv = KMF_OK;
1374	}
1375
1376	/*
1377	 * Start searching for certificates that match the criteria and
1378	 * delete them.
1379	 */
1380	objlist = NULL;
1381	rv = search_certs(handle, certlabel, issuer, subject, serial,
1382	    private, validity, &objlist, &numObjects);
1383
1384	if (rv == KMF_OK && objlist != NULL) {
1385		OBJLIST *node = objlist;
1386
1387		while (node != NULL) {
1388			CK_RV ckrv;
1389			ckrv = C_DestroyObject(kmfh->pk11handle, node->handle);
1390			if (ckrv != CKR_OK) {
1391				SET_ERROR(kmfh, ckrv);
1392				rv = KMF_ERR_INTERNAL;
1393				break;
1394			}
1395			node = node->next;
1396		}
1397		free_objlist(objlist);
1398	}
1399
1400	if (rv == KMF_OK && numObjects == 0)
1401		rv = KMF_ERR_CERT_NOT_FOUND;
1402
1403out:
1404	return (rv);
1405}
1406
1407static CK_RV
1408gendsa_keypair(KMF_HANDLE *kmfh, boolean_t storekey,
1409	CK_OBJECT_HANDLE *pubKey,
1410	CK_OBJECT_HANDLE *priKey)
1411{
1412	CK_RV ckrv = CKR_OK;
1413	CK_SESSION_HANDLE hSession = kmfh->pk11handle;
1414	static CK_ULONG	dsaKeyType = CKK_DSA;
1415	static CK_BBOOL	true = TRUE;
1416	static CK_BBOOL	false = FALSE;
1417	static CK_OBJECT_CLASS	priClass = CKO_PRIVATE_KEY;
1418	static CK_OBJECT_CLASS	pubClass = CKO_PUBLIC_KEY;
1419
1420	static CK_BYTE ckDsaPrime[128] = {
1421	0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
1422	0xcf, 0xdd, 0xf9, 0xae, 0x3e, 0x39, 0x7f, 0x9c,
1423	0xa7, 0x73, 0xc3, 0x00, 0xa3, 0x50, 0x67, 0xc3,
1424	0xab, 0x49, 0x2c, 0xea, 0x59, 0x10, 0xa4, 0xbc,
1425	0x09, 0x94, 0xa9, 0x05, 0x3b, 0x0d, 0x35, 0x3c,
1426	0x55, 0x52, 0x47, 0xf0, 0xe3, 0x72, 0x5b, 0xe8,
1427	0x72, 0xa0, 0x71, 0x1c, 0x23, 0x4f, 0x6d, 0xe8,
1428	0xac, 0xe5, 0x21, 0x1b, 0xc0, 0xd8, 0x42, 0xd3,
1429	0x87, 0xae, 0x83, 0x5e, 0x52, 0x7e, 0x46, 0x09,
1430	0xb5, 0xc7, 0x3d, 0xd6, 0x00, 0xf5, 0xf2, 0x9c,
1431	0x84, 0x30, 0x81, 0x7e, 0x7b, 0x30, 0x5b, 0xd5,
1432	0xab, 0xd0, 0x2f, 0x21, 0xb3, 0xd8, 0xed, 0xdb,
1433	0x97, 0x77, 0xe4, 0x7e, 0x6c, 0xcc, 0xb9, 0x6b,
1434	0xdd, 0xaa, 0x96, 0x04, 0xe7, 0xd4, 0x55, 0x11,
1435	0x53, 0xab, 0xba, 0x95, 0x9a, 0xa2, 0x8c, 0x27,
1436	0xd9, 0xcf, 0xad, 0xf3, 0xcf, 0x3a, 0x0c, 0x4b};
1437
1438	static CK_BYTE ckDsaSubPrime[20] = {
1439	0xa4, 0x5f, 0x2a, 0x27, 0x09, 0x49, 0xb6, 0xfe,
1440	0x73, 0xeb, 0x95, 0x7d, 0x00, 0xf3, 0x42, 0xfc,
1441	0x78, 0x47, 0xb0, 0xd5};
1442
1443	static CK_BYTE ckDsaBase[128] = {
1444	0x5c, 0x57, 0x16, 0x49, 0xef, 0xc8, 0xfb, 0x4b,
1445	0xee, 0x07, 0x45, 0x3b, 0x6a, 0x1d, 0xf3, 0xe5,
1446	0xeb, 0xee, 0xad, 0x11, 0x13, 0xe3, 0x52, 0xe3,
1447	0x0d, 0xc0, 0x21, 0x25, 0xfa, 0xf0, 0x93, 0x1c,
1448	0x53, 0x4d, 0xdc, 0x0d, 0x76, 0xd2, 0xfe, 0xc2,
1449	0xd7, 0x72, 0x64, 0x69, 0x53, 0x3d, 0x33, 0xbd,
1450	0xe1, 0x34, 0xf2, 0x5a, 0x67, 0x83, 0xe0, 0xd3,
1451	0x1c, 0xd6, 0x41, 0x4d, 0x16, 0xe8, 0x6c, 0x5a,
1452	0x07, 0x95, 0x21, 0x9a, 0xa3, 0xc4, 0xb9, 0x05,
1453	0x9d, 0x11, 0xcb, 0xc8, 0xc4, 0x9d, 0x00, 0x1a,
1454	0xf4, 0x85, 0x2a, 0xa9, 0x20, 0x3c, 0xba, 0x67,
1455	0xe5, 0xed, 0x31, 0xb2, 0x11, 0xfb, 0x1f, 0x73,
1456	0xec, 0x61, 0x29, 0xad, 0xc7, 0x68, 0xb2, 0x3f,
1457	0x38, 0xea, 0xd9, 0x87, 0x83, 0x9e, 0x7e, 0x19,
1458	0x18, 0xdd, 0xc2, 0xc3, 0x5b, 0x16, 0x6d, 0xce,
1459	0xcf, 0x88, 0x91, 0x07, 0xe0, 0x2b, 0xa8, 0x54 };
1460
1461	static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
1462	{ CKA_CLASS, &pubClass, sizeof (pubClass) },
1463	{ CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
1464	{ CKA_TOKEN, &true, sizeof (true)},
1465	{ CKA_PRIVATE, &false, sizeof (false)},
1466	{ CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) },
1467	{ CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)},
1468	{ CKA_BASE, &ckDsaBase, sizeof (ckDsaBase) },
1469	{ CKA_VERIFY, &true, sizeof (true) },
1470};
1471
1472#define	NUMBER_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1473					sizeof (CK_ATTRIBUTE))
1474#define	MAX_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1475				    sizeof (CK_ATTRIBUTE))
1476
1477	static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
1478	{CKA_CLASS, &priClass, sizeof (priClass)},
1479	{CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
1480	{CKA_TOKEN, &true, sizeof (true)},
1481	{CKA_PRIVATE, &true, sizeof (true)},
1482	{CKA_SIGN, &true, sizeof (true)},
1483	};
1484
1485#define	NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1486					sizeof (CK_ATTRIBUTE))
1487#define	MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1488				sizeof (CK_ATTRIBUTE))
1489	CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
1490
1491	SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
1492	    (storekey ? &true : &false), sizeof (CK_BBOOL));
1493
1494	ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1495	    ckDsaPubKeyTemplate,
1496	    (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1497	    ckDsaPriKeyTemplate,
1498	    (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1499	    pubKey, priKey);
1500	if (ckrv != CKR_OK) {
1501		SET_ERROR(kmfh, ckrv);
1502		return (KMF_ERR_KEYGEN_FAILED);
1503	}
1504
1505	return (ckrv);
1506}
1507
1508static CK_RV
1509genrsa_keypair(KMF_HANDLE *kmfh, CK_ULONG modulusBits,
1510	boolean_t storekey, KMF_BIGINT *rsaexp,
1511	CK_OBJECT_HANDLE *pubKey,
1512	CK_OBJECT_HANDLE *priKey)
1513{
1514	CK_RV ckrv = CKR_OK;
1515	CK_SESSION_HANDLE hSession = kmfh->pk11handle;
1516	CK_ATTRIBUTE rsaPubKeyTemplate[16];
1517	CK_ATTRIBUTE rsaPriKeyTemplate[16];
1518	CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0};
1519	int numpubattr = 0, numpriattr = 0;
1520	static CK_BYTE	PubExpo[3] = {0x01, 0x00, 0x01};
1521	static CK_BBOOL	true = TRUE;
1522	static CK_BBOOL	false = FALSE;
1523
1524	SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN,
1525	    (storekey ? &true : &false), sizeof (CK_BBOOL));
1526	numpubattr++;
1527
1528	SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS,
1529	    &modulusBits, sizeof (modulusBits));
1530	numpubattr++;
1531
1532	if (rsaexp != NULL && (rsaexp->len > 0 && rsaexp->val != NULL)) {
1533		SETATTR(rsaPubKeyTemplate, numpubattr,
1534		    CKA_PUBLIC_EXPONENT,
1535		    rsaexp->val, rsaexp->len);
1536		numpubattr++;
1537	} else {
1538		SETATTR(rsaPubKeyTemplate, numpubattr,
1539		    CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo));
1540		numpubattr++;
1541	}
1542	SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT,
1543	    &true, sizeof (true));
1544	numpubattr++;
1545	SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY,
1546	    &true, sizeof (true));
1547	numpubattr++;
1548	SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP,
1549	    &true, sizeof (true));
1550	numpubattr++;
1551
1552	SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN,
1553	    (storekey ? &true : &false), sizeof (CK_BBOOL));
1554	numpriattr++;
1555	SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true,
1556	    sizeof (true));
1557	numpriattr++;
1558	SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true,
1559	    sizeof (true));
1560	numpriattr++;
1561	SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true,
1562	    sizeof (true));
1563	numpriattr++;
1564	SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true,
1565	    sizeof (true));
1566	numpriattr++;
1567
1568	ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1569	    rsaPubKeyTemplate, numpubattr,
1570	    rsaPriKeyTemplate, numpriattr,
1571	    pubKey, priKey);
1572	if (ckrv != CKR_OK) {
1573		SET_ERROR(kmfh, ckrv);
1574		return (ckrv);
1575	}
1576
1577	return (ckrv);
1578}
1579
1580static CK_RV
1581genecc_keypair(KMF_HANDLE *kmfh,
1582	boolean_t ontoken,
1583	KMF_OID *curveoid,
1584	CK_OBJECT_HANDLE *pubKey,
1585	CK_OBJECT_HANDLE *priKey)
1586{
1587	CK_RV ckrv;
1588	CK_SESSION_HANDLE hSession = kmfh->pk11handle;
1589	CK_MECHANISM keyGenMech = {CKM_EC_KEY_PAIR_GEN, NULL, 0};
1590	const ulong_t publicKey = CKO_PUBLIC_KEY;
1591	const ulong_t privateKey = CKO_PRIVATE_KEY;
1592	const ulong_t keytype = CKK_EC;
1593	static CK_BBOOL	true = TRUE;
1594	static CK_BBOOL	false = FALSE;
1595	CK_ATTRIBUTE public_template[6];
1596	CK_ATTRIBUTE private_template[6];
1597	int numpubattr, numpriattr;
1598
1599	numpubattr = 0;
1600	SETATTR(public_template, numpubattr, CKA_CLASS,
1601	    &publicKey, sizeof (publicKey));
1602	numpubattr++;
1603	SETATTR(public_template, numpubattr, CKA_KEY_TYPE,
1604	    &keytype, sizeof (keytype));
1605	numpubattr++;
1606	SETATTR(public_template, numpubattr, CKA_EC_PARAMS,
1607	    curveoid->Data, curveoid->Length);
1608	numpubattr++;
1609	SETATTR(public_template, numpubattr, CKA_TOKEN,
1610	    ontoken ? &true : &false, sizeof (true));
1611	numpubattr++;
1612	SETATTR(public_template, numpubattr, CKA_VERIFY,
1613	    &true, sizeof (true));
1614	numpubattr++;
1615	SETATTR(public_template, numpubattr, CKA_PRIVATE,
1616	    &false, sizeof (false));
1617	numpubattr++;
1618
1619	numpriattr = 0;
1620	SETATTR(private_template, numpriattr, CKA_CLASS,
1621	    &privateKey, sizeof (privateKey));
1622	numpriattr++;
1623	SETATTR(private_template, numpriattr, CKA_KEY_TYPE,
1624	    &keytype, sizeof (keytype));
1625	numpriattr++;
1626	SETATTR(private_template, numpriattr, CKA_TOKEN,
1627	    ontoken ? &true : &false, sizeof (true));
1628	numpriattr++;
1629	SETATTR(private_template, numpriattr, CKA_PRIVATE,
1630	    &true, sizeof (true));
1631	numpriattr++;
1632	SETATTR(private_template, numpriattr, CKA_SIGN,
1633	    &true, sizeof (true));
1634	numpriattr++;
1635	SETATTR(private_template, numpriattr, CKA_DERIVE,
1636	    &true, sizeof (true));
1637	numpriattr++;
1638
1639	ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1640	    public_template, numpubattr,
1641	    private_template, numpriattr,
1642	    pubKey, priKey);
1643	if (ckrv != CKR_OK) {
1644		SET_ERROR(kmfh, ckrv);
1645		return (ckrv);
1646	}
1647
1648	return (ckrv);
1649}
1650
1651KMF_RETURN
1652KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
1653	int numattr,
1654	KMF_ATTRIBUTE *attlist)
1655{
1656	KMF_RETURN rv = KMF_OK;
1657	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1658	KMF_DATA IDInput, IDOutput;
1659	KMF_CREDENTIAL *cred;
1660	KMF_KEY_ALG keytype = KMF_RSA;
1661	KMF_KEY_HANDLE *pubkey, *privkey;
1662
1663	CK_RV			ckrv = 0;
1664	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1665	CK_ATTRIBUTE labelattr[1];
1666	CK_ATTRIBUTE idattr[1];
1667	CK_OBJECT_HANDLE pubKey, priKey;
1668
1669	char IDHashData[SHA1_HASH_LENGTH];
1670	static CK_ULONG	modulusBits = 1024;
1671	uint32_t	modulusBits_size = sizeof (CK_ULONG);
1672	SHA1_CTX ctx;
1673	boolean_t storekey = TRUE;
1674	char *keylabel = NULL;
1675
1676	if (kmfh == NULL)
1677		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1678
1679	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1680		return (KMF_ERR_NO_TOKEN_SELECTED);
1681
1682	/* "storekey" is optional. Default is TRUE */
1683	(void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attlist, numattr,
1684	    &storekey, NULL);
1685
1686	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attlist, numattr);
1687	if (cred == NULL)
1688		return (KMF_ERR_BAD_PARAMETER);
1689
1690	rv = pk11_authenticate(handle, cred);
1691	if (rv != KMF_OK)
1692		return (rv);
1693
1694	/* keytype is optional.  KMF_RSA is default */
1695	(void) kmf_get_attr(KMF_KEYALG_ATTR, attlist, numattr,
1696	    (void *)&keytype, NULL);
1697
1698	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
1699	if (pubkey == NULL)
1700		return (KMF_ERR_BAD_PARAMETER);
1701
1702	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist, numattr);
1703	if (privkey == NULL)
1704		return (KMF_ERR_BAD_PARAMETER);
1705
1706	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1707	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1708	if (keytype == KMF_RSA) {
1709		CK_BYTE *modulus = NULL;
1710		CK_ULONG modulusLength = 0;
1711		KMF_BIGINT *rsaexp = NULL;
1712		CK_ATTRIBUTE modattr[1];
1713
1714		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attlist, numattr,
1715		    &modulusBits, &modulusBits_size);
1716		if (rv == KMF_ERR_ATTR_NOT_FOUND)
1717			/* Default modulusBits = 1024 */
1718			rv = KMF_OK;
1719		if (rv != KMF_OK)
1720			return (KMF_ERR_BAD_PARAMETER);
1721
1722		rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist, numattr);
1723
1724		/* Generate the RSA keypair */
1725		ckrv = genrsa_keypair(kmfh, modulusBits, storekey,
1726		    rsaexp, &pubKey, &priKey);
1727
1728		if (ckrv != CKR_OK)
1729			return (KMF_ERR_BAD_PARAMETER);
1730
1731		privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1732		privkey->keyalg = KMF_RSA;
1733		privkey->keyclass = KMF_ASYM_PRI;
1734		privkey->keyp = (void *)priKey;
1735
1736		pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1737		pubkey->keyalg = KMF_RSA;
1738		pubkey->keyclass = KMF_ASYM_PUB;
1739		pubkey->keyp = (void *)pubKey;
1740
1741		SETATTR(modattr, 0, CKA_MODULUS, NULL, modulusLength);
1742		/* Get the Modulus field to use as input for creating the ID */
1743		ckrv = C_GetAttributeValue(kmfh->pk11handle,
1744		    (CK_OBJECT_HANDLE)pubKey, modattr, 1);
1745		if (ckrv != CKR_OK) {
1746			SET_ERROR(kmfh, ckrv);
1747			return (KMF_ERR_BAD_PARAMETER);
1748		}
1749
1750		modulusLength = modattr[0].ulValueLen;
1751		modulus = malloc(modulusLength);
1752		if (modulus == NULL)
1753			return (KMF_ERR_MEMORY);
1754
1755		modattr[0].pValue = modulus;
1756		ckrv = C_GetAttributeValue(kmfh->pk11handle,
1757		    (CK_OBJECT_HANDLE)pubKey, modattr, 1);
1758		if (ckrv != CKR_OK) {
1759			SET_ERROR(kmfh, ckrv);
1760			free(modulus);
1761			return (KMF_ERR_BAD_PARAMETER);
1762		}
1763
1764		IDInput.Data = modulus;
1765		IDInput.Length = modulusLength;
1766
1767	} else if (keytype == KMF_DSA) {
1768		CK_BYTE *keyvalue;
1769		CK_ULONG valueLen;
1770		CK_ATTRIBUTE valattr[1];
1771
1772		/* Generate the DSA keypair */
1773		ckrv = gendsa_keypair(kmfh, storekey, &pubKey, &priKey);
1774		if (ckrv != CKR_OK)
1775			return (KMF_ERR_BAD_PARAMETER);
1776
1777		privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1778		privkey->keyalg = KMF_DSA;
1779		privkey->keyclass = KMF_ASYM_PRI;
1780		privkey->keyp = (void *)priKey;
1781
1782		pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1783		pubkey->keyalg = KMF_DSA;
1784		pubkey->keyclass = KMF_ASYM_PUB;
1785		pubkey->keyp = (void *)pubKey;
1786
1787		/* Get the Public Value to use as input for creating the ID */
1788		SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen);
1789
1790		ckrv = C_GetAttributeValue(hSession,
1791		    (CK_OBJECT_HANDLE)pubKey, valattr, 1);
1792		if (ckrv != CKR_OK) {
1793			SET_ERROR(kmfh, ckrv);
1794			return (KMF_ERR_BAD_PARAMETER);
1795		}
1796
1797		valueLen = valattr[0].ulValueLen;
1798		keyvalue = malloc(valueLen);
1799		if (keyvalue == NULL)
1800			return (KMF_ERR_MEMORY);
1801
1802		valattr[0].pValue = keyvalue;
1803		ckrv = C_GetAttributeValue(hSession,
1804		    (CK_OBJECT_HANDLE)pubKey, valattr, 1);
1805		if (ckrv != CKR_OK) {
1806			SET_ERROR(kmfh, ckrv);
1807			free(keyvalue);
1808			return (KMF_ERR_BAD_PARAMETER);
1809		}
1810
1811		IDInput.Data = keyvalue;
1812		IDInput.Length = valueLen;
1813	} else if (keytype == KMF_ECDSA) {
1814		CK_BYTE *keyvalue;
1815		CK_ULONG valueLen;
1816		CK_ATTRIBUTE valattr[1];
1817		KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
1818		    attlist, numattr);
1819
1820		if (eccoid == NULL)
1821			return (KMF_ERR_BAD_PARAMETER);
1822
1823		ckrv = genecc_keypair(kmfh, storekey, eccoid,
1824		    &pubKey, &priKey);
1825		if (ckrv != CKR_OK)
1826			return (KMF_ERR_BAD_PARAMETER);
1827
1828		privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1829		privkey->keyalg = KMF_ECDSA;
1830		privkey->keyclass = KMF_ASYM_PRI;
1831		privkey->keyp = (void *)priKey;
1832
1833		pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1834		pubkey->keyalg = KMF_ECDSA;
1835		pubkey->keyclass = KMF_ASYM_PUB;
1836		pubkey->keyp = (void *)pubKey;
1837
1838		/* Get the EC_POINT to use as input for creating the ID */
1839		SETATTR(valattr, 0, CKA_EC_POINT, NULL, &valueLen);
1840
1841		ckrv = C_GetAttributeValue(hSession,
1842		    (CK_OBJECT_HANDLE)pubKey, valattr, 1);
1843		if (ckrv != CKR_OK) {
1844			SET_ERROR(kmfh, ckrv);
1845			return (KMF_ERR_BAD_PARAMETER);
1846		}
1847
1848		valueLen = valattr[0].ulValueLen;
1849		keyvalue = malloc(valueLen);
1850		if (keyvalue == NULL)
1851			return (KMF_ERR_MEMORY);
1852
1853		valattr[0].pValue = keyvalue;
1854		ckrv = C_GetAttributeValue(hSession,
1855		    (CK_OBJECT_HANDLE)pubKey, valattr, 1);
1856		if (ckrv != CKR_OK) {
1857			SET_ERROR(kmfh, ckrv);
1858			free(keyvalue);
1859			return (KMF_ERR_BAD_PARAMETER);
1860		}
1861
1862		IDInput.Data = keyvalue;
1863		IDInput.Length = valueLen;
1864	} else {
1865		return (KMF_ERR_BAD_PARAMETER);
1866	}
1867
1868	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attlist, numattr);
1869	if (keylabel != NULL && strlen(keylabel)) {
1870		SETATTR(labelattr, 0, CKA_LABEL, keylabel, strlen(keylabel));
1871
1872		/* Set the CKA_LABEL if one was indicated */
1873		if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1874		    labelattr, 1)) != CKR_OK) {
1875			SET_ERROR(kmfh, ckrv);
1876			rv = KMF_ERR_INTERNAL;
1877			goto cleanup;
1878		}
1879		pubkey->keylabel = (char *)strdup(keylabel);
1880		if (pubkey->keylabel == NULL) {
1881			rv = KMF_ERR_MEMORY;
1882			goto cleanup;
1883		}
1884		if ((ckrv = C_SetAttributeValue(hSession, priKey,
1885		    labelattr, 1)) != CKR_OK) {
1886			SET_ERROR(kmfh, ckrv);
1887			rv = KMF_ERR_INTERNAL;
1888			goto cleanup;
1889		}
1890		privkey->keylabel = (char *)strdup(keylabel);
1891		if (privkey->keylabel == NULL) {
1892			rv = KMF_ERR_MEMORY;
1893			goto cleanup;
1894		}
1895	} else {
1896		rv = KMF_OK;
1897	}
1898
1899	/* Now, assign a CKA_ID value so it can be searched */
1900	/* ID_Input was assigned above in the RSA or DSA keygen section */
1901	IDOutput.Data = (uchar_t *)IDHashData;
1902	IDOutput.Length = sizeof (IDHashData);
1903
1904	SHA1Init(&ctx);
1905	SHA1Update(&ctx, IDInput.Data, IDInput.Length);
1906	SHA1Final(IDOutput.Data, &ctx);
1907
1908	IDOutput.Length = SHA1_DIGEST_LENGTH;
1909
1910	free(IDInput.Data);
1911
1912	if (rv != CKR_OK) {
1913		goto cleanup;
1914	}
1915	SETATTR(idattr, 0, CKA_ID, IDOutput.Data, IDOutput.Length);
1916	if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1917	    idattr, 1)) != CKR_OK) {
1918		SET_ERROR(kmfh, ckrv);
1919		rv = KMF_ERR_INTERNAL;
1920		goto cleanup;
1921	}
1922	if ((ckrv = C_SetAttributeValue(hSession, priKey,
1923	    idattr, 1)) != CKR_OK) {
1924		SET_ERROR(kmfh, ckrv);
1925		rv = KMF_ERR_INTERNAL;
1926		goto cleanup;
1927	}
1928
1929cleanup:
1930	if (rv != KMF_OK) {
1931		if (pubKey != CK_INVALID_HANDLE)
1932			(void) C_DestroyObject(hSession, pubKey);
1933		if (priKey != CK_INVALID_HANDLE)
1934			(void) C_DestroyObject(hSession, priKey);
1935
1936		if (privkey->keylabel)
1937			free(privkey->keylabel);
1938		if (pubkey->keylabel)
1939			free(pubkey->keylabel);
1940	}
1941	return (rv);
1942}
1943
1944KMF_RETURN
1945KMFPK11_DeleteKey(KMF_HANDLE_T handle,
1946	int numattr, KMF_ATTRIBUTE *attrlist)
1947{
1948	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1949	CK_RV ckrv = CKR_OK;
1950	KMF_RETURN rv = KMF_OK;
1951	KMF_KEY_HANDLE *key;
1952	KMF_CREDENTIAL cred;
1953	boolean_t destroy = B_TRUE;
1954
1955	if (kmfh == NULL)
1956		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1957
1958	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1959		return (KMF_ERR_NO_TOKEN_SELECTED);
1960
1961	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1962	if (key == NULL || key->keyp == NULL)
1963		return (KMF_ERR_BAD_PARAMETER);
1964
1965	if (key->keyclass != KMF_ASYM_PUB &&
1966	    key->keyclass != KMF_ASYM_PRI &&
1967	    key->keyclass != KMF_SYMMETRIC)
1968		return (KMF_ERR_BAD_KEY_CLASS);
1969
1970	/* "destroy" is optional. Default is TRUE */
1971	(void) kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1972	    (void *)&destroy, NULL);
1973
1974	if (destroy) {
1975		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1976		    (void *)&cred, NULL);
1977		if (rv != KMF_OK)
1978			return (KMF_ERR_BAD_PARAMETER);
1979
1980		rv = pk11_authenticate(handle, &cred);
1981		if (rv != KMF_OK) {
1982			return (rv);
1983		}
1984	}
1985
1986	if (!key->israw && destroy)
1987		ckrv = C_DestroyObject(kmfh->pk11handle,
1988		    (CK_OBJECT_HANDLE)key->keyp);
1989
1990	if (ckrv != CKR_OK) {
1991		SET_ERROR(kmfh, ckrv);
1992		/* Report authentication failures to the caller */
1993		if (ckrv == CKR_PIN_EXPIRED || ckrv == CKR_SESSION_READ_ONLY)
1994			rv = KMF_ERR_AUTH_FAILED;
1995		else
1996			rv = KMF_ERR_INTERNAL;
1997	}
1998	return (rv);
1999}
2000
2001KMF_RETURN
2002KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
2003	KMF_OID *algOID,
2004	KMF_DATA *tobesigned,
2005	KMF_DATA *output)
2006{
2007	KMF_RETURN		rv = KMF_OK;
2008	CK_RV			ckrv;
2009	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2010	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2011	CK_MECHANISM		mechanism;
2012	CK_MECHANISM_TYPE	mechtype, hashmech;
2013	CK_KEY_TYPE		keytype;
2014	KMF_ALGORITHM_INDEX	AlgId;
2015	KMF_DATA		hashData = {NULL, 0};
2016	uchar_t			digest[1024];
2017	CK_ATTRIBUTE		subprime = { CKA_SUBPRIME, NULL, 0 };
2018
2019	if (kmfh == NULL)
2020		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2021
2022	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2023		return (KMF_ERR_NO_TOKEN_SELECTED);
2024
2025	if (keyp == NULL || algOID == NULL ||
2026	    tobesigned == NULL || output == NULL)
2027		return (KMF_ERR_BAD_PARAMETER);
2028
2029	/* These functions are available to the plugin from libkmf */
2030	AlgId = x509_algoid_to_algid(algOID);
2031	if (AlgId == KMF_ALGID_NONE)
2032		return (KMF_ERR_BAD_PARAMETER);
2033
2034	/* Get the PKCS11 signing key type and mechtype */
2035	if (get_pk11_data(AlgId, &keytype, &mechtype, &hashmech, 0))
2036		return (KMF_ERR_BAD_PARAMETER);
2037
2038	(void) memset(digest, 0, sizeof (digest));
2039	hashData.Data = digest;
2040	hashData.Length = sizeof (digest);
2041	rv = PKCS_DigestData(handle, hSession, hashmech, tobesigned, &hashData,
2042	    (mechtype == CKM_RSA_PKCS));
2043	if (rv)
2044		return (rv);
2045
2046	if (mechtype == CKM_DSA && hashmech == CKM_SHA256) {
2047		/*
2048		 * FIPS 186-3 says that when signing with DSA
2049		 * the hash must be truncated to the size of the
2050		 * subprime.
2051		 */
2052		ckrv = C_GetAttributeValue(hSession,
2053		    (CK_OBJECT_HANDLE)keyp->keyp,
2054		    &subprime, 1);
2055		if (ckrv != CKR_OK)  {
2056			SET_ERROR(kmfh, ckrv);
2057			return (KMF_ERR_INTERNAL);
2058		}
2059		hashData.Length = subprime.ulValueLen;
2060	}
2061
2062	/* the mechtype from the 'get_pk11_info' refers to the signing */
2063	mechanism.mechanism = mechtype;
2064	mechanism.pParameter = NULL;
2065	mechanism.ulParameterLen = 0;
2066
2067	ckrv = C_SignInit(hSession, &mechanism, (CK_OBJECT_HANDLE)keyp->keyp);
2068	if (ckrv != CKR_OK) {
2069		SET_ERROR(kmfh, ckrv);
2070		return (KMF_ERR_INTERNAL);
2071	}
2072
2073	ckrv = C_Sign(hSession,	hashData.Data, hashData.Length,
2074	    output->Data, (CK_ULONG *)&output->Length);
2075
2076	if (ckrv != CKR_OK) {
2077		SET_ERROR(kmfh, ckrv);
2078		return (KMF_ERR_INTERNAL);
2079	}
2080
2081	return (KMF_OK);
2082}
2083
2084KMF_RETURN
2085KMFPK11_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
2086{
2087	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2088
2089	*msgstr = NULL;
2090	if (kmfh->lasterr.errcode != 0) {
2091		char *e = pkcs11_strerror(kmfh->lasterr.errcode);
2092		if (e == NULL || (*msgstr = (char *)strdup(e)) == NULL) {
2093			return (KMF_ERR_MEMORY);
2094		}
2095	}
2096
2097	return (KMF_OK);
2098}
2099
2100static CK_RV
2101getObjectKeytype(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2102	CK_ULONG *keytype)
2103{
2104	CK_RV rv = CKR_OK;
2105	CK_ATTRIBUTE templ;
2106	CK_ULONG len = sizeof (CK_ULONG);
2107	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2108
2109	templ.type = CKA_KEY_TYPE;
2110	templ.pValue = keytype;
2111	templ.ulValueLen = len;
2112
2113	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2114
2115	return (rv);
2116
2117}
2118
2119static CK_RV
2120getObjectLabel(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2121	char **outlabel)
2122{
2123	CK_RV rv = CKR_OK;
2124	CK_ATTRIBUTE templ;
2125	char	Label[BUFSIZ];
2126	CK_ULONG len = sizeof (Label);
2127	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2128
2129	(void) memset(Label, 0, len);
2130	templ.type = CKA_LABEL;
2131	templ.pValue = Label;
2132	templ.ulValueLen = len;
2133
2134	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2135	if (rv == CKR_OK) {
2136		*outlabel = (char *)strdup(Label);
2137	} else {
2138		*outlabel = NULL;
2139	}
2140	return (rv);
2141}
2142
2143static CK_RV
2144getObjectKeyclass(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2145	KMF_KEY_CLASS *keyclass)
2146{
2147	CK_RV rv = CKR_OK;
2148	CK_ATTRIBUTE templ;
2149	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2150	CK_OBJECT_CLASS class;
2151
2152	templ.type = CKA_CLASS;
2153	templ.pValue = &class;
2154	templ.ulValueLen = sizeof (CK_OBJECT_CLASS);
2155
2156	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2157	if (rv == CKR_OK) {
2158		if (class == CKO_PUBLIC_KEY) {
2159			*keyclass = KMF_ASYM_PUB;
2160		} else if (class == CKO_PRIVATE_KEY) {
2161			*keyclass = KMF_ASYM_PRI;
2162		} else if (class == CKO_SECRET_KEY) {
2163			*keyclass = KMF_SYMMETRIC;
2164		}
2165	} else {
2166		*keyclass = KMF_KEYCLASS_NONE;
2167	}
2168	return (rv);
2169}
2170
2171KMF_RETURN
2172KMFPK11_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2173    KMF_ATTRIBUTE *attrlist)
2174{
2175	KMF_X509_SPKI *pubkey;
2176	KMF_X509_CERTIFICATE *SignerCert = NULL;
2177	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2178	KMF_RETURN rv = KMF_OK;
2179	CK_RV ckrv = CKR_OK;
2180	CK_ATTRIBUTE templ[4];
2181	CK_OBJECT_HANDLE pri_obj = CK_INVALID_HANDLE;
2182	CK_ULONG obj_count;
2183	CK_OBJECT_CLASS certClass = CKO_PRIVATE_KEY;
2184	CK_BBOOL true = TRUE;
2185	KMF_DATA Id = { NULL, 0 };
2186	KMF_KEY_HANDLE *key = NULL;
2187	KMF_DATA *cert = NULL;
2188	KMF_CREDENTIAL cred;
2189	KMF_ENCODE_FORMAT format = KMF_FORMAT_UNDEF;
2190	CK_ULONG keytype;
2191
2192	/* Get the key handle */
2193	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2194	if (key == NULL)
2195		return (KMF_ERR_BAD_PARAMETER);
2196
2197	/* Get the optional encoded format */
2198	(void) kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
2199	    (void *)&format, NULL);
2200
2201	/* Decode the signer cert so we can get the SPKI data */
2202	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2203	if (cert == NULL || cert->Data == NULL)
2204		return (KMF_ERR_BAD_PARAMETER);
2205
2206	if ((rv = DerDecodeSignedCertificate(cert,
2207	    &SignerCert)) != KMF_OK)
2208		return (rv);
2209
2210	/* Get the public key info from the signer certificate */
2211	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
2212
2213	/* Generate an ID from the SPKI data */
2214	rv = GetIDFromSPKI(pubkey, &Id);
2215	if (rv != KMF_OK) {
2216		goto errout;
2217	}
2218
2219	/* Get the credential and login */
2220	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2221	    (void *)&cred, NULL);
2222	if (rv != KMF_OK)
2223		return (KMF_ERR_BAD_PARAMETER);
2224
2225	rv = pk11_authenticate(handle, &cred);
2226	if (rv != KMF_OK) {
2227		return (rv);
2228	}
2229
2230	/* Start searching */
2231	SETATTR(templ, 0, CKA_CLASS, &certClass, sizeof (certClass));
2232	SETATTR(templ, 1, CKA_TOKEN, &true, sizeof (true));
2233	SETATTR(templ, 2, CKA_PRIVATE, &true, sizeof (true));
2234	SETATTR(templ, 3, CKA_ID, Id.Data, Id.Length);
2235
2236	if ((ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, 4)) != CKR_OK) {
2237		SET_ERROR(kmfh, ckrv);
2238		rv = KMF_ERR_INTERNAL;
2239		goto errout;
2240	}
2241
2242	if ((ckrv = C_FindObjects(kmfh->pk11handle, &pri_obj, 1,
2243	    &obj_count)) != CKR_OK) {
2244		SET_ERROR(kmfh, ckrv);
2245		rv = KMF_ERR_INTERNAL;
2246		goto errout;
2247	}
2248
2249	if (obj_count == 0) {
2250		SET_ERROR(kmfh, ckrv);
2251		rv = KMF_ERR_INTERNAL;
2252		goto errout;
2253	}
2254
2255	key->kstype = KMF_KEYSTORE_PK11TOKEN;
2256	key->keyclass = KMF_ASYM_PRI;
2257	key->keyp = (void *)pri_obj;
2258	key->israw = FALSE;
2259
2260	(void) C_FindObjectsFinal(kmfh->pk11handle);
2261
2262	ckrv = getObjectLabel(handle, (CK_OBJECT_HANDLE)key->keyp,
2263	    &key->keylabel);
2264	if (ckrv != CKR_OK) {
2265		SET_ERROR(handle, ckrv);
2266		rv = KMF_ERR_INTERNAL;
2267	} else {
2268		rv = KMF_OK;
2269	}
2270
2271	/*
2272	 * The key->keyalg value is needed if we need to convert the key
2273	 * to raw key.  However, the key->keyalg value will not be set if
2274	 * this function is not called thru the kmf_find_prikey_by_cert()
2275	 * framework function. To be safe, we will get the keytype from
2276	 * the key object and set key->keyalg value here.
2277	 */
2278	ckrv = getObjectKeytype(handle, (CK_OBJECT_HANDLE)key->keyp,
2279	    &keytype);
2280	if (ckrv != CKR_OK) {
2281		SET_ERROR(handle, ckrv);
2282		rv = KMF_ERR_INTERNAL;
2283	} else {
2284		rv = KMF_OK;
2285	}
2286
2287	if (keytype == CKK_RSA)
2288		key->keyalg = KMF_RSA;
2289	else if (keytype == CKK_DSA)
2290		key->keyalg = KMF_DSA;
2291	else if (keytype == CKK_EC)
2292		key->keyalg = KMF_ECDSA;
2293	else {
2294		/* For asymmetric keys, we only support RSA and DSA */
2295		rv = KMF_ERR_KEY_NOT_FOUND;
2296		goto errout;
2297	}
2298
2299	if (rv == KMF_OK && format == KMF_FORMAT_RAWKEY) {
2300		KMF_RAW_KEY_DATA *rkey = NULL;
2301		rv = keyObj2RawKey(handle, key, &rkey);
2302		if (rv == KMF_OK) {
2303			key->keyp = rkey;
2304			key->israw = TRUE;
2305		}
2306	}
2307
2308errout:
2309	if (Id.Data != NULL)
2310		free(Id.Data);
2311
2312	if (SignerCert != NULL) {
2313		kmf_free_signed_cert(SignerCert);
2314		free(SignerCert);
2315	}
2316	return (rv);
2317}
2318
2319KMF_RETURN
2320KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2321	KMF_OID *algOID, KMF_DATA *ciphertext,
2322	KMF_DATA *output)
2323{
2324	CK_RV			ckrv;
2325	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2326	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2327	CK_MECHANISM		mechanism;
2328	CK_MECHANISM_TYPE	mechtype;
2329	CK_KEY_TYPE		keytype;
2330	KMF_ALGORITHM_INDEX	AlgId;
2331	CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
2332	uint8_t *in_data, *out_data;
2333	int i, blocks;
2334	CK_ATTRIBUTE ckTemplate[1];
2335
2336	if (kmfh == NULL)
2337		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2338
2339	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2340		return (KMF_ERR_NO_TOKEN_SELECTED);
2341
2342	if (key == NULL || algOID == NULL ||
2343	    ciphertext == NULL || output == NULL)
2344		return (KMF_ERR_BAD_PARAMETER);
2345
2346	AlgId = x509_algoid_to_algid(algOID);
2347	if (AlgId == KMF_ALGID_NONE)
2348		return (KMF_ERR_BAD_PARAMETER);
2349
2350	/* Map the Algorithm ID to a PKCS#11 mechanism */
2351	if (get_pk11_data(AlgId, &keytype, &mechtype, NULL, 0))
2352		return (KMF_ERR_BAD_PARAMETER);
2353
2354	mechanism.mechanism = mechtype;
2355	mechanism.pParameter = NULL;
2356	mechanism.ulParameterLen = 0;
2357
2358	SETATTR(ckTemplate, 0, CKA_MODULUS, (CK_BYTE *)NULL,
2359	    sizeof (CK_ULONG));
2360
2361	/* Get the modulus length */
2362	ckrv = C_GetAttributeValue(hSession,
2363	    (CK_OBJECT_HANDLE)key->keyp, ckTemplate, 1);
2364
2365	if (ckrv != CKR_OK)  {
2366		SET_ERROR(kmfh, ckrv);
2367		return (KMF_ERR_INTERNAL);
2368	}
2369
2370	block_len = ckTemplate[0].ulValueLen;
2371
2372	/* Compute the number of times to do single-part decryption */
2373	blocks = ciphertext->Length/block_len;
2374
2375	out_data = output->Data;
2376	in_data = ciphertext->Data;
2377	out_len = block_len - 11;
2378
2379	for (i = 0; i < blocks; i++) {
2380		ckrv = C_DecryptInit(hSession, &mechanism,
2381		    (CK_OBJECT_HANDLE)key->keyp);
2382
2383		if (ckrv != CKR_OK) {
2384			SET_ERROR(kmfh, ckrv);
2385			return (KMF_ERR_INTERNAL);
2386		}
2387
2388		ckrv = C_Decrypt(hSession, in_data, block_len,
2389		    out_data, (CK_ULONG *)&out_len);
2390
2391		if (ckrv != CKR_OK) {
2392			SET_ERROR(kmfh, ckrv);
2393			return (KMF_ERR_INTERNAL);
2394		}
2395
2396		out_data += out_len;
2397		total_decrypted += out_len;
2398		in_data += block_len;
2399
2400	}
2401
2402	output->Length = total_decrypted;
2403	return (KMF_OK);
2404}
2405
2406static void
2407attr2bigint(CK_ATTRIBUTE_PTR attr, KMF_BIGINT *big)
2408{
2409	big->val = attr->pValue;
2410	big->len = attr->ulValueLen;
2411}
2412
2413static KMF_RETURN
2414get_bigint_attr(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
2415	CK_ATTRIBUTE_TYPE attrtype, KMF_BIGINT *bigint)
2416{
2417	CK_RV ckrv;
2418	CK_ATTRIBUTE attr;
2419
2420	attr.type = attrtype;
2421	attr.pValue = NULL;
2422	attr.ulValueLen = 0;
2423
2424	if ((ckrv = C_GetAttributeValue(sess, obj,
2425	    &attr, 1)) != CKR_OK) {
2426		/* Mask this error so the caller can continue */
2427		if (ckrv == CKR_ATTRIBUTE_TYPE_INVALID)
2428			return (KMF_OK);
2429		else
2430			return (KMF_ERR_INTERNAL);
2431	}
2432	if (attr.ulValueLen > 0 && bigint != NULL) {
2433		attr.pValue = malloc(attr.ulValueLen);
2434		if (attr.pValue == NULL)
2435			return (KMF_ERR_MEMORY);
2436
2437		if ((ckrv = C_GetAttributeValue(sess, obj,
2438		    &attr, 1)) != CKR_OK)
2439		if (ckrv != CKR_OK) {
2440			free(attr.pValue);
2441			return (KMF_ERR_INTERNAL);
2442		}
2443
2444		bigint->val = attr.pValue;
2445		bigint->len = attr.ulValueLen;
2446	}
2447	return (KMF_OK);
2448}
2449
2450static KMF_RETURN
2451get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2452{
2453	KMF_RETURN rv = KMF_OK;
2454	CK_RV ckrv;
2455	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2456	CK_ATTRIBUTE rsa_pri_attrs[2] = {
2457		{ CKA_MODULUS, NULL, 0 },
2458		{ CKA_PUBLIC_EXPONENT, NULL, 0 }
2459	};
2460	CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2461	int i;
2462
2463	if (rawrsa == NULL)
2464		return (KMF_ERR_BAD_PARAMETER);
2465
2466	(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2467	if ((ckrv = C_GetAttributeValue(sess, obj,
2468	    rsa_pri_attrs, count)) != CKR_OK) {
2469		SET_ERROR(kmfh, ckrv);
2470		/* Tell the caller know why the key data cannot be retrieved. */
2471		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2472			return (KMF_ERR_SENSITIVE_KEY);
2473		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2474			return (KMF_ERR_UNEXTRACTABLE_KEY);
2475		else
2476			return (KMF_ERR_INTERNAL);
2477	}
2478
2479	/* Allocate memory for each attribute. */
2480	for (i = 0; i < count; i++) {
2481		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2482		    rsa_pri_attrs[i].ulValueLen == 0) {
2483			rsa_pri_attrs[i].ulValueLen = 0;
2484			continue;
2485		}
2486		if ((rsa_pri_attrs[i].pValue =
2487		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2488			rv = KMF_ERR_MEMORY;
2489			goto end;
2490		}
2491	}
2492	/* Now that we have space, really get the attributes */
2493	if ((ckrv = C_GetAttributeValue(sess, obj,
2494	    rsa_pri_attrs, count)) != CKR_OK) {
2495		SET_ERROR(kmfh, ckrv);
2496		rv = KMF_ERR_INTERNAL;
2497		goto end;
2498	}
2499	i = 0;
2500	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2501	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2502
2503	/* Now get the optional parameters */
2504	rv = get_bigint_attr(sess, obj, CKA_PRIVATE_EXPONENT, &rawrsa->priexp);
2505	if (rv != KMF_OK)
2506		goto end;
2507	rv = get_bigint_attr(sess, obj, CKA_PRIME_1, &rawrsa->prime1);
2508	if (rv != KMF_OK)
2509		goto end;
2510	rv = get_bigint_attr(sess, obj, CKA_PRIME_2, &rawrsa->prime2);
2511	if (rv != KMF_OK)
2512		goto end;
2513	rv = get_bigint_attr(sess, obj, CKA_EXPONENT_1, &rawrsa->exp1);
2514	if (rv != KMF_OK)
2515		goto end;
2516	rv = get_bigint_attr(sess, obj, CKA_EXPONENT_2, &rawrsa->exp2);
2517	if (rv != KMF_OK)
2518		goto end;
2519	rv = get_bigint_attr(sess, obj, CKA_COEFFICIENT, &rawrsa->coef);
2520	if (rv != KMF_OK)
2521		goto end;
2522
2523end:
2524	if (rv != KMF_OK) {
2525		for (i = 0; i < count; i++) {
2526			if (rsa_pri_attrs[i].pValue != NULL)
2527				free(rsa_pri_attrs[i].pValue);
2528		}
2529		if (rawrsa->priexp.val)
2530			free(rawrsa->priexp.val);
2531		if (rawrsa->prime1.val)
2532			free(rawrsa->prime1.val);
2533		if (rawrsa->prime2.val)
2534			free(rawrsa->prime2.val);
2535		if (rawrsa->exp1.val)
2536			free(rawrsa->exp1.val);
2537		if (rawrsa->exp2.val)
2538			free(rawrsa->exp2.val);
2539		if (rawrsa->coef.val)
2540			free(rawrsa->coef.val);
2541		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2542	}
2543	return (rv);
2544}
2545
2546#define	DSA_PRIME_BUFSIZE	CHARLEN2BIGNUMLEN(1024)	/* 8192 bits */
2547#define	DSA_PRIVATE_BUFSIZE	BIG_CHUNKS_FOR_160BITS	/* 160 bits */
2548
2549/*
2550 * This function calculates the pubkey value from the prime,
2551 * base and private key values of a DSA key.
2552 */
2553static KMF_RETURN
2554compute_dsa_pubvalue(KMF_RAW_DSA_KEY *rawdsa)
2555{
2556	KMF_RETURN rv = KMF_OK;
2557	BIGNUM p, g, x, y;
2558	BIG_ERR_CODE err;
2559	uchar_t *pubvalue;
2560	uint32_t pubvalue_len;
2561
2562	if ((err = big_init1(&p, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2563		rv = KMF_ERR_MEMORY;
2564		return (rv);
2565	}
2566	bytestring2bignum(&p, rawdsa->prime.val, rawdsa->prime.len);
2567
2568	if ((err = big_init1(&g, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2569		rv = KMF_ERR_MEMORY;
2570		goto ret1;
2571	}
2572	bytestring2bignum(&g, rawdsa->base.val, rawdsa->base.len);
2573
2574	if ((err = big_init1(&x, DSA_PRIVATE_BUFSIZE, NULL, 0)) != BIG_OK) {
2575		rv = KMF_ERR_MEMORY;
2576		goto ret2;
2577	}
2578	bytestring2bignum(&x, rawdsa->value.val, rawdsa->value.len);
2579
2580	if ((err = big_init1(&y, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2581		rv = KMF_ERR_MEMORY;
2582		goto ret3;
2583	}
2584
2585	err = big_modexp(&y, &g, &x, &p, NULL);
2586	if (err != BIG_OK) {
2587		rv = KMF_ERR_INTERNAL;
2588		goto ret3;
2589	}
2590
2591	pubvalue_len = y.len * (int)sizeof (uint32_t);
2592	if ((pubvalue = malloc(pubvalue_len)) == NULL) {
2593		rv = KMF_ERR_MEMORY;
2594		goto ret4;
2595	}
2596	bignum2bytestring(pubvalue, &y, pubvalue_len);
2597
2598	rawdsa->pubvalue.val = pubvalue;
2599	rawdsa->pubvalue.len = pubvalue_len;
2600
2601ret4:
2602	big_finish(&y);
2603ret3:
2604	big_finish(&x);
2605ret2:
2606	big_finish(&g);
2607ret1:
2608	big_finish(&p);
2609	return (rv);
2610}
2611
2612static KMF_RETURN
2613get_raw_ec(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_EC_KEY *rawec)
2614{
2615	KMF_RETURN rv = KMF_OK;
2616	CK_RV ckrv;
2617	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2618	CK_ATTRIBUTE	ec_attrs[2] = {
2619		{ CKA_EC_PARAMS, NULL, 0},
2620		{ CKA_VALUE, NULL, 0}
2621	};
2622	CK_ULONG	count = sizeof (ec_attrs) / sizeof (CK_ATTRIBUTE);
2623	int		i;
2624
2625	if ((ckrv = C_GetAttributeValue(sess, obj,
2626	    ec_attrs, 2)) != CKR_OK) {
2627		SET_ERROR(kmfh, ckrv);
2628
2629		/* Tell the caller know why the key data cannot be retrieved. */
2630		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2631			return (KMF_ERR_SENSITIVE_KEY);
2632		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2633			return (KMF_ERR_UNEXTRACTABLE_KEY);
2634		return (KMF_ERR_INTERNAL);
2635	}
2636	for (i = 0; i < count; i++) {
2637		if (ec_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2638		    ec_attrs[i].ulValueLen == 0) {
2639			ec_attrs[i].ulValueLen = 0;
2640			continue;
2641		}
2642		if ((ec_attrs[i].pValue =
2643		    malloc(ec_attrs[i].ulValueLen)) == NULL) {
2644			rv = KMF_ERR_MEMORY;
2645			goto end;
2646		}
2647	}
2648	if ((ckrv = C_GetAttributeValue(sess, obj,
2649	    ec_attrs, count)) != CKR_OK) {
2650		SET_ERROR(kmfh, ckrv);
2651		rv = KMF_ERR_INTERNAL;
2652		goto end;
2653	}
2654
2655	rawec->params.Data = ec_attrs[0].pValue;
2656	rawec->params.Length = ec_attrs[0].ulValueLen;
2657	rawec->value.val = ec_attrs[1].pValue;
2658	rawec->value.len = ec_attrs[1].ulValueLen;
2659
2660end:
2661	if (rv != KMF_OK) {
2662		for (i = 0; i < count; i++) {
2663			if (ec_attrs[i].pValue != NULL)
2664				free(ec_attrs[i].pValue);
2665		}
2666		(void) memset(rawec, 0, sizeof (KMF_RAW_EC_KEY));
2667	}
2668	return (rv);
2669}
2670
2671static KMF_RETURN
2672get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2673{
2674	KMF_RETURN rv = KMF_OK;
2675	CK_RV ckrv;
2676	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2677	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2678		{ CKA_PRIME, NULL, 0 },
2679		{ CKA_SUBPRIME, NULL, 0 },
2680		{ CKA_BASE, NULL, 0 },
2681		{ CKA_VALUE, NULL, 0 }
2682	};
2683	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2684	int		i;
2685
2686	if ((ckrv = C_GetAttributeValue(sess, obj,
2687	    dsa_pri_attrs, count)) != CKR_OK) {
2688		SET_ERROR(kmfh, ckrv);
2689
2690		/* Tell the caller know why the key data cannot be retrieved. */
2691		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2692			return (KMF_ERR_SENSITIVE_KEY);
2693		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2694			return (KMF_ERR_UNEXTRACTABLE_KEY);
2695		return (KMF_ERR_INTERNAL);
2696	}
2697
2698	/* Allocate memory for each attribute. */
2699	for (i = 0; i < count; i++) {
2700		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2701		    dsa_pri_attrs[i].ulValueLen == 0) {
2702			dsa_pri_attrs[i].ulValueLen = 0;
2703			continue;
2704		}
2705		if ((dsa_pri_attrs[i].pValue =
2706		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2707			rv = KMF_ERR_MEMORY;
2708			goto end;
2709		}
2710	}
2711	if ((ckrv = C_GetAttributeValue(sess, obj,
2712	    dsa_pri_attrs, count)) != CKR_OK) {
2713		SET_ERROR(kmfh, ckrv);
2714		rv = KMF_ERR_INTERNAL;
2715		goto end;
2716	}
2717
2718	/* Fill in all the temp variables.  They are all required. */
2719	i = 0;
2720	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2721	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2722	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2723	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2724
2725	/* Compute the public key value and store it */
2726	rv = compute_dsa_pubvalue(rawdsa);
2727
2728end:
2729	if (rv != KMF_OK) {
2730		for (i = 0; i < count; i++) {
2731			if (dsa_pri_attrs[i].pValue != NULL)
2732				free(dsa_pri_attrs[i].pValue);
2733		}
2734		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2735	}
2736	return (rv);
2737}
2738
2739static KMF_RETURN
2740get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2741{
2742	KMF_RETURN rv = KMF_OK;
2743	CK_RV	ckrv;
2744	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2745	CK_ATTRIBUTE	sym_attr[1];
2746	CK_ULONG	value_len = 0;
2747
2748	/* find the key length first */
2749	sym_attr[0].type = CKA_VALUE;
2750	sym_attr[0].pValue = NULL;
2751	sym_attr[0].ulValueLen = value_len;
2752	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2753		rawsym->keydata.val = NULL;
2754		rawsym->keydata.len = 0;
2755		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2756			return (KMF_ERR_SENSITIVE_KEY);
2757		} else if (ckrv == CKR_KEY_UNEXTRACTABLE) {
2758			return (KMF_ERR_UNEXTRACTABLE_KEY);
2759		} else {
2760			SET_ERROR(kmfh, ckrv);
2761			return (KMF_ERR_INTERNAL);
2762		}
2763	}
2764
2765	/* Allocate memory for pValue */
2766	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2767	if (sym_attr[0].pValue == NULL) {
2768		return (KMF_ERR_MEMORY);
2769	}
2770
2771	/* get the key data */
2772	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2773		SET_ERROR(kmfh, ckrv);
2774		free(sym_attr[0].pValue);
2775		return (KMF_ERR_INTERNAL);
2776	}
2777
2778	rawsym->keydata.val = sym_attr[0].pValue;
2779	rawsym->keydata.len = sym_attr[0].ulValueLen;
2780	return (rv);
2781}
2782
2783static KMF_RETURN
2784keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2785	KMF_RAW_KEY_DATA **outkey)
2786{
2787	KMF_RETURN rv = KMF_OK;
2788	KMF_RAW_KEY_DATA *rkey;
2789	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2790
2791	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2792	if (rkey == NULL)
2793		return (KMF_ERR_MEMORY);
2794
2795	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2796
2797	rkey->keytype = inkey->keyalg;
2798
2799	if (inkey->keyalg == KMF_RSA) {
2800		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2801		    &rkey->rawdata.rsa);
2802	} else if (inkey->keyalg == KMF_DSA) {
2803		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2804		    &rkey->rawdata.dsa);
2805	} else if (inkey->keyalg == KMF_AES ||
2806	    inkey->keyalg == KMF_RC4 ||
2807	    inkey->keyalg == KMF_DES ||
2808	    inkey->keyalg == KMF_DES3 ||
2809	    inkey->keyalg == KMF_GENERIC_SECRET) {
2810		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2811		    &rkey->rawdata.sym);
2812		/*
2813		 * If sensitive or non-extractable, mark them as such
2814		 * but return "OK" status so the keys get counted
2815		 * when doing FindKey operations.
2816		 */
2817		if (rv == KMF_ERR_SENSITIVE_KEY) {
2818			rkey->sensitive = B_TRUE;
2819			rv = KMF_OK;
2820		} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
2821			rkey->not_extractable = B_TRUE;
2822			rv = KMF_OK;
2823		}
2824	} else if (inkey->keyalg == KMF_ECDSA) {
2825		rv = get_raw_ec(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2826		    &rkey->rawdata.ec);
2827	} else {
2828		rv = KMF_ERR_BAD_PARAMETER;
2829	}
2830
2831	if (rv == KMF_OK) {
2832		*outkey = rkey;
2833	} else if (rkey != NULL) {
2834		free(rkey);
2835		*outkey = NULL;
2836	}
2837
2838	return (rv);
2839}
2840
2841
2842static KMF_RETURN
2843kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2844{
2845	switch (keyalg) {
2846	case KMF_RSA:
2847		*type = CKK_RSA;
2848		break;
2849	case KMF_DSA:
2850		*type = CKK_DSA;
2851		break;
2852	case KMF_ECDSA:
2853		*type = CKK_EC;
2854		break;
2855	case KMF_AES:
2856		*type = CKK_AES;
2857		break;
2858	case KMF_RC4:
2859		*type = CKK_RC4;
2860		break;
2861	case KMF_DES:
2862		*type = CKK_DES;
2863		break;
2864	case KMF_DES3:
2865		*type = CKK_DES3;
2866		break;
2867	case KMF_GENERIC_SECRET:
2868		*type = CKK_GENERIC_SECRET;
2869		break;
2870	default:
2871		return (KMF_ERR_BAD_KEY_TYPE);
2872	}
2873
2874	return (KMF_OK);
2875}
2876
2877static int
2878IDStringToData(char *idstr, KMF_DATA *iddata)
2879{
2880	int len, i;
2881	char *iddup, *byte;
2882	uint_t lvalue;
2883
2884	if (idstr == NULL || !strlen(idstr))
2885		return (-1);
2886
2887	iddup = (char *)strdup(idstr);
2888	if (iddup == NULL)
2889		return (KMF_ERR_MEMORY);
2890
2891	len = strlen(iddup) / 3  + 1;
2892	iddata->Data = malloc(len);
2893	if (iddata->Data == NULL)
2894		return (KMF_ERR_MEMORY);
2895	(void) memset(iddata->Data, 0, len);
2896	iddata->Length = len;
2897
2898	byte = strtok(iddup, ":");
2899	if (byte == NULL) {
2900		free(iddup);
2901		free(iddata->Data);
2902		iddata->Data = NULL;
2903		iddata->Length = 0;
2904		return (-1);
2905	}
2906
2907	i = 0;
2908	do {
2909		(void) sscanf(byte, "%x", &lvalue);
2910		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2911		byte = strtok(NULL, ":");
2912	} while (byte != NULL && i < len);
2913
2914	iddata->Length = i;
2915	free(iddup);
2916	return (0);
2917}
2918
2919KMF_RETURN
2920KMFPK11_FindKey(KMF_HANDLE_T handle,
2921	int numattr, KMF_ATTRIBUTE *attrlist)
2922{
2923	KMF_RETURN rv = KMF_OK;
2924	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2925	uint32_t want_keys, i;
2926	CK_RV ckrv;
2927	CK_ATTRIBUTE pTmpl[10];
2928	CK_OBJECT_CLASS class;
2929	CK_BBOOL true = TRUE;
2930	CK_ULONG alg;
2931	boolean_t is_token = B_TRUE, is_private = B_FALSE;
2932	KMF_KEY_HANDLE *keys;
2933	uint32_t *numkeys;
2934	KMF_CREDENTIAL *cred = NULL;
2935	KMF_KEY_CLASS keyclass = KMF_KEYCLASS_NONE;
2936	char *findLabel, *idstr;
2937	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
2938	KMF_ENCODE_FORMAT format;
2939
2940	if (kmfh == NULL)
2941		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2942
2943	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2944		return (KMF_ERR_NO_TOKEN_SELECTED);
2945
2946	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2947	if (numkeys == NULL)
2948		return (KMF_ERR_BAD_PARAMETER);
2949
2950	if (*numkeys > 0)
2951		want_keys = *numkeys;
2952	else
2953		want_keys = MAXINT; /* count them all */
2954
2955	/* keyclass is optional */
2956	(void) kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2957	    (void *)&keyclass, NULL);
2958
2959	if (keyclass == KMF_ASYM_PUB) {
2960		class = CKO_PUBLIC_KEY;
2961	} else if (keyclass == KMF_ASYM_PRI) {
2962		class = CKO_PRIVATE_KEY;
2963	} else if (keyclass == KMF_SYMMETRIC) {
2964		class = CKO_SECRET_KEY;
2965	}
2966
2967	rv = kmf_get_attr(KMF_TOKEN_BOOL_ATTR, attrlist, numattr,
2968	    (void *)&is_token, NULL);
2969	if (rv != KMF_OK)
2970		return (rv);
2971
2972	i = 0;
2973	if (is_token) {
2974		SETATTR(pTmpl, i, CKA_TOKEN, &true, sizeof (true));
2975		i++;
2976	}
2977
2978	if (keyclass != KMF_KEYCLASS_NONE) {
2979		SETATTR(pTmpl, i, CKA_CLASS, &class, sizeof (class));
2980		i++;
2981	}
2982
2983	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2984
2985	if (findLabel != NULL && strlen(findLabel)) {
2986		SETATTR(pTmpl, i, CKA_LABEL, findLabel, strlen(findLabel));
2987		i++;
2988	}
2989	/* keytype is optional */
2990	(void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2991	    (void *)&keytype, NULL);
2992
2993	if (keytype != 0) {
2994		rv = kmf2pk11keytype(keytype, &alg);
2995		if (rv != KMF_OK) {
2996			return (KMF_ERR_BAD_KEY_TYPE);
2997		}
2998		SETATTR(pTmpl, i, CKA_KEY_TYPE, &alg, sizeof (alg));
2999		i++;
3000	}
3001
3002	idstr = kmf_get_attr_ptr(KMF_IDSTR_ATTR, attrlist, numattr);
3003
3004	if (idstr != NULL) {
3005		KMF_DATA iddata = { NULL, 0 };
3006
3007		/*
3008		 * ID String parameter is assumed to be of form:
3009		 * XX:XX:XX:XX:XX ... :XX
3010		 * where XX is a hex number.
3011		 *
3012		 * We must convert this back to binary in order to
3013		 * use it in a search.
3014		 */
3015		rv = IDStringToData(idstr, &iddata);
3016		if (rv == KMF_OK) {
3017			SETATTR(pTmpl, i, CKA_ID, iddata.Data, iddata.Length);
3018			i++;
3019		} else {
3020			return (rv);
3021		}
3022	}
3023
3024	/* is_private is optional */
3025	(void) kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
3026	    (void *)&is_private, NULL);
3027
3028	if (is_private) {
3029		SETATTR(pTmpl, i, CKA_PRIVATE, &true, sizeof (true));
3030		i++;
3031	}
3032
3033	/*
3034	 * Authenticate if the object is a token object,
3035	 * a private or secred key, or if the user passed in credentials.
3036	 */
3037	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3038	if (cred != NULL) {
3039		rv = pk11_authenticate(handle, cred);
3040		if (rv != KMF_OK)
3041			return (rv);
3042	}
3043
3044	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3045	/* it is okay to have "keys" contains NULL */
3046
3047	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
3048	if (ckrv == CKR_OK) {
3049		CK_ULONG obj_count, n = 0;
3050		while (ckrv == CKR_OK && n < want_keys) {
3051			CK_OBJECT_HANDLE hObj;
3052
3053			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
3054			    1, &obj_count);
3055			if (ckrv == CKR_OK && obj_count == 1) {
3056				if (keys != NULL) {
3057					CK_ULONG keytype;
3058					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
3059					keys[n].israw = FALSE;
3060					keys[n].keyp = (void *)hObj;
3061
3062					ckrv = getObjectKeytype(handle,
3063					    (CK_OBJECT_HANDLE)keys[n].keyp,
3064					    &keytype);
3065					if (ckrv != CKR_OK)
3066						goto end;
3067
3068					ckrv = getObjectLabel(handle,
3069					    (CK_OBJECT_HANDLE)keys[n].keyp,
3070					    &(keys[n].keylabel));
3071					if (ckrv != CKR_OK)
3072						goto end;
3073
3074					if (keyclass == KMF_KEYCLASS_NONE) {
3075						ckrv = getObjectKeyclass(handle,
3076						    (CK_OBJECT_HANDLE)
3077						    keys[n].keyp,
3078						    &(keys[n].keyclass));
3079						if (ckrv != CKR_OK)
3080							goto end;
3081					} else {
3082						keys[n].keyclass = keyclass;
3083					}
3084					if (keytype == CKK_RSA) {
3085						keys[n].keyalg = KMF_RSA;
3086					} else if (keytype == CKK_DSA) {
3087						keys[n].keyalg = KMF_DSA;
3088					} else if (keytype == CKK_EC) {
3089						keys[n].keyalg = KMF_ECDSA;
3090					} else if (keytype == CKK_AES) {
3091						keys[n].keyalg = KMF_AES;
3092						keys[n].keyclass =
3093						    KMF_SYMMETRIC;
3094					} else if (keytype == CKK_RC4) {
3095						keys[n].keyalg = KMF_RC4;
3096						keys[n].keyclass =
3097						    KMF_SYMMETRIC;
3098					} else if (keytype == CKK_DES) {
3099						keys[n].keyalg = KMF_DES;
3100						keys[n].keyclass =
3101						    KMF_SYMMETRIC;
3102					} else if (keytype == CKK_DES3) {
3103						keys[n].keyalg = KMF_DES3;
3104						keys[n].keyclass =
3105						    KMF_SYMMETRIC;
3106					} else if (keytype ==
3107					    CKK_GENERIC_SECRET) {
3108						keys[n].keyalg =
3109						    KMF_GENERIC_SECRET;
3110						keys[n].keyclass =
3111						    KMF_SYMMETRIC;
3112					}
3113
3114				}
3115				n++;
3116			} else {
3117				break;
3118			}
3119		}
3120		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
3121
3122		/* "numkeys" indicates the number that were actually found */
3123		*numkeys = n;
3124	}
3125
3126	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
3127		if ((rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
3128		    numattr, (void *)&format, NULL)) == KMF_OK) {
3129			if (format == KMF_FORMAT_RAWKEY ||
3130			    format == KMF_FORMAT_PEM) {
3131				/* Convert keys to "rawkey" format */
3132				for (i = 0; i < (*numkeys); i++) {
3133					KMF_RAW_KEY_DATA *rkey = NULL;
3134					rv = keyObj2RawKey(handle, &keys[i],
3135					    &rkey);
3136					if (rv == KMF_OK) {
3137						keys[i].keyp = rkey;
3138						keys[i].israw = TRUE;
3139					} else {
3140						break;
3141					}
3142				}
3143			}
3144		} else {
3145			rv = KMF_OK; /* format is optional */
3146		}
3147	}
3148
3149end:
3150	if (ckrv != CKR_OK) {
3151		SET_ERROR(kmfh, ckrv);
3152		/* Report authentication failures to the caller */
3153		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3154		    ckrv == CKR_PIN_INCORRECT ||
3155		    ckrv == CKR_PIN_INVALID ||
3156		    ckrv == CKR_PIN_EXPIRED ||
3157		    ckrv == CKR_PIN_LOCKED ||
3158		    ckrv == CKR_SESSION_READ_ONLY)
3159			rv = KMF_ERR_AUTH_FAILED;
3160		else
3161			rv = KMF_ERR_INTERNAL;
3162	} else if ((*numkeys) == 0) {
3163		rv = KMF_ERR_KEY_NOT_FOUND;
3164	}
3165
3166	return (rv);
3167}
3168
3169static char *
3170convertDate(char *fulldate)
3171{
3172	struct tm tms;
3173	char newtime[9];
3174
3175	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
3176
3177	if (tms.tm_year < 69)
3178		tms.tm_year += 100;
3179
3180	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
3181
3182	newtime[8] = 0;
3183
3184	/* memory returned must be freed by the caller */
3185	return ((char *)strdup(newtime));
3186}
3187
3188static KMF_RETURN
3189store_raw_key(KMF_HANDLE_T handle,
3190	KMF_ATTRIBUTE *attrlist, int numattr,
3191	KMF_RAW_KEY_DATA *rawkey)
3192{
3193	KMF_RETURN rv = KMF_OK;
3194	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3195	int i;
3196	CK_RV		ckrv = CKR_OK;
3197	CK_ATTRIBUTE	templ[32];
3198	CK_OBJECT_HANDLE keyobj;
3199	CK_KEY_TYPE	keytype;
3200	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
3201	CK_BBOOL	cktrue = TRUE;
3202	CK_DATE		startdate, enddate;
3203	KMF_DATA	id = {NULL, 0};
3204	KMF_DATA	subject = {NULL, 0};
3205	KMF_X509EXT_KEY_USAGE kuext;
3206	KMF_X509_CERTIFICATE *x509 = NULL;
3207	CK_BBOOL	kufound = B_FALSE;
3208	KMF_DATA	*cert = NULL;
3209	char		*notbefore = NULL, *start = NULL;
3210	char		*notafter = NULL, *end = NULL;
3211	char		*keylabel = NULL;
3212	KMF_CREDENTIAL	*cred = NULL;
3213
3214	if (kmfh == NULL)
3215		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
3216
3217	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3218		return (KMF_ERR_NO_TOKEN_SELECTED);
3219
3220	if (rawkey->keytype == KMF_RSA)
3221		keytype = CKK_RSA;
3222	else if (rawkey->keytype == KMF_DSA)
3223		keytype = CKK_DSA;
3224	else if (rawkey->keytype == KMF_ECDSA)
3225		keytype = CKK_EC;
3226	else
3227		return (KMF_ERR_BAD_PARAMETER);
3228
3229	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3230	if (cred != NULL) {
3231		rv = pk11_authenticate(handle, cred);
3232		if (rv != KMF_OK)
3233			return (rv);
3234	}
3235
3236	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3237	/*
3238	 * If the caller did not specify a label, see if the raw key
3239	 * came with one (possible if it came from a PKCS#12 file).
3240	 */
3241	if (keylabel == NULL) {
3242		keylabel = rawkey->label;
3243	}
3244
3245	i = 0;
3246	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
3247	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
3248	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
3249	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
3250	if (keytype != CKK_EC)
3251		SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
3252
3253	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
3254	if (cert != NULL) {
3255		id.Data = NULL;
3256		id.Length = 0;
3257		rv = kmf_get_cert_id_data(cert, &id);
3258		if (rv != KMF_OK) {
3259			goto cleanup;
3260		}
3261
3262		rv = DerDecodeSignedCertificate((const KMF_DATA *)cert, &x509);
3263		if (rv != KMF_OK) {
3264			goto cleanup;
3265		}
3266
3267		rv = DerEncodeName(&x509->certificate.subject, &subject);
3268		if (rv != KMF_OK) {
3269			goto cleanup;
3270		}
3271		SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length);
3272		i++;
3273
3274		rv = kmf_get_cert_start_date_str(handle, cert, &notbefore);
3275		if (rv != KMF_OK) {
3276			goto cleanup;
3277		}
3278		start = convertDate(notbefore);
3279		free(notbefore);
3280
3281		rv = kmf_get_cert_end_date_str(handle, cert, &notafter);
3282		if (rv != KMF_OK) {
3283			goto cleanup;
3284		}
3285		end = convertDate(notafter);
3286		free(notafter);
3287		if (id.Data != NULL && id.Data != NULL && id.Length > 0) {
3288			SETATTR(templ, i, CKA_ID, id.Data, id.Length);
3289			i++;
3290		}
3291		if (start != NULL) {
3292			/*
3293			 * This makes some potentially dangerous assumptions:
3294			 *  1. that the startdate in the parameter block is
3295			 * properly formatted as YYYYMMDD
3296			 *  2. That the CK_DATE structure is always the same.
3297			 */
3298			(void) memcpy(&startdate, start, sizeof (CK_DATE));
3299			SETATTR(templ, i, CKA_START_DATE, &startdate,
3300			    sizeof (startdate));
3301			i++;
3302		}
3303		if (end != NULL) {
3304			(void) memcpy(&enddate, end, sizeof (CK_DATE));
3305			SETATTR(templ, i, CKA_END_DATE, &enddate,
3306			    sizeof (enddate));
3307			i++;
3308		}
3309
3310		if ((rv = kmf_get_cert_ku(cert, &kuext)) != KMF_OK &&
3311		    rv != KMF_ERR_EXTENSION_NOT_FOUND)
3312			goto cleanup;
3313
3314		kufound = (rv == KMF_OK);
3315		rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND */
3316	}
3317
3318	/*
3319	 * Only set the KeyUsage stuff if the KU extension was present.
3320	 */
3321	if (kufound) {
3322		CK_BBOOL	condition;
3323
3324		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
3325		    B_TRUE : B_FALSE;
3326		SETATTR(templ, i, CKA_UNWRAP, &condition, sizeof (CK_BBOOL));
3327		i++;
3328		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
3329		    B_TRUE : B_FALSE;
3330		SETATTR(templ, i, CKA_DECRYPT, &condition, sizeof (CK_BBOOL));
3331		i++;
3332		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3333		    B_TRUE : B_FALSE;
3334		SETATTR(templ, i, CKA_SIGN, &condition,	sizeof (CK_BBOOL));
3335		i++;
3336		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3337		    B_TRUE : B_FALSE;
3338		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
3339		    sizeof (CK_BBOOL));
3340		i++;
3341
3342	}
3343
3344	if (keylabel != NULL) {
3345		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3346		i++;
3347	}
3348	if (id.Data == NULL && rawkey->id.Data != NULL) {
3349		SETATTR(templ, i, CKA_ID, rawkey->id.Data,
3350		    rawkey->id.Length);
3351		i++;
3352	}
3353	if (keytype == CKK_RSA) {
3354		SETATTR(templ, i, CKA_MODULUS,
3355		    rawkey->rawdata.rsa.mod.val,
3356		    rawkey->rawdata.rsa.mod.len);
3357		i++;
3358		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
3359		    rawkey->rawdata.rsa.pubexp.val,
3360		    rawkey->rawdata.rsa.pubexp.len);
3361		i++;
3362		if (rawkey->rawdata.rsa.priexp.val != NULL) {
3363			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
3364			    rawkey->rawdata.rsa.priexp.val,
3365			    rawkey->rawdata.rsa.priexp.len);
3366			i++;
3367		}
3368		if (rawkey->rawdata.rsa.prime1.val != NULL) {
3369			SETATTR(templ, i, CKA_PRIME_1,
3370			    rawkey->rawdata.rsa.prime1.val,
3371			    rawkey->rawdata.rsa.prime1.len);
3372			i++;
3373		}
3374		if (rawkey->rawdata.rsa.prime2.val != NULL) {
3375			SETATTR(templ, i, CKA_PRIME_2,
3376			    rawkey->rawdata.rsa.prime2.val,
3377			    rawkey->rawdata.rsa.prime2.len);
3378			i++;
3379		}
3380		if (rawkey->rawdata.rsa.exp1.val != NULL) {
3381			SETATTR(templ, i, CKA_EXPONENT_1,
3382			    rawkey->rawdata.rsa.exp1.val,
3383			    rawkey->rawdata.rsa.exp1.len);
3384			i++;
3385		}
3386		if (rawkey->rawdata.rsa.exp2.val != NULL) {
3387			SETATTR(templ, i, CKA_EXPONENT_2,
3388			    rawkey->rawdata.rsa.exp2.val,
3389			    rawkey->rawdata.rsa.exp2.len);
3390			i++;
3391		}
3392		if (rawkey->rawdata.rsa.coef.val != NULL) {
3393			SETATTR(templ, i, CKA_COEFFICIENT,
3394			    rawkey->rawdata.rsa.coef.val,
3395			    rawkey->rawdata.rsa.coef.len);
3396			i++;
3397		}
3398	} else if (keytype == CKK_DSA) {
3399		SETATTR(templ, i, CKA_PRIME,
3400		    rawkey->rawdata.dsa.prime.val,
3401		    rawkey->rawdata.dsa.prime.len);
3402		i++;
3403		SETATTR(templ, i, CKA_SUBPRIME,
3404		    rawkey->rawdata.dsa.subprime.val,
3405		    rawkey->rawdata.dsa.subprime.len);
3406		i++;
3407		SETATTR(templ, i, CKA_BASE,
3408		    rawkey->rawdata.dsa.base.val,
3409		    rawkey->rawdata.dsa.base.len);
3410		i++;
3411		SETATTR(templ, i, CKA_VALUE,
3412		    rawkey->rawdata.dsa.value.val,
3413		    rawkey->rawdata.dsa.value.len);
3414		i++;
3415	} else if (keytype == CKK_EC) {
3416		SETATTR(templ, i, CKA_SIGN, &cktrue, sizeof (cktrue));
3417		i++;
3418		SETATTR(templ, i, CKA_DERIVE, &cktrue, sizeof (cktrue));
3419		i++;
3420		SETATTR(templ, i, CKA_VALUE,
3421		    rawkey->rawdata.ec.value.val,
3422		    rawkey->rawdata.ec.value.len);
3423		i++;
3424		SETATTR(templ, i, CKA_EC_PARAMS,
3425		    rawkey->rawdata.ec.params.Data,
3426		    rawkey->rawdata.ec.params.Length);
3427		i++;
3428	}
3429
3430	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
3431	if (ckrv != CKR_OK) {
3432		SET_ERROR(kmfh, ckrv);
3433
3434		/* Report authentication failures to the caller */
3435		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3436		    ckrv == CKR_PIN_INCORRECT ||
3437		    ckrv == CKR_PIN_INVALID ||
3438		    ckrv == CKR_PIN_EXPIRED ||
3439		    ckrv == CKR_PIN_LOCKED ||
3440		    ckrv == CKR_SESSION_READ_ONLY)
3441			rv = KMF_ERR_AUTH_FAILED;
3442		else
3443			rv = KMF_ERR_INTERNAL;
3444	}
3445cleanup:
3446	if (start != NULL)
3447		free(start);
3448	if (end != NULL)
3449		free(end);
3450	kmf_free_data(&id);
3451	kmf_free_data(&subject);
3452	kmf_free_signed_cert(x509);
3453	free(x509);
3454
3455	return (rv);
3456}
3457
3458KMF_RETURN
3459KMFPK11_CreateSymKey(KMF_HANDLE_T handle,
3460    int numattr, KMF_ATTRIBUTE *attrlist)
3461{
3462	KMF_RETURN		rv = KMF_OK;
3463	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3464	CK_RV			ckrv;
3465	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3466	CK_OBJECT_HANDLE	keyhandle;
3467	CK_MECHANISM		keyGenMech;
3468	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3469	CK_ULONG		secKeyType;
3470	CK_ULONG		secKeyLen;	/* for RC4 and AES */
3471	CK_BBOOL		true = TRUE;
3472	CK_BBOOL		false = FALSE;
3473	CK_ATTRIBUTE		templ[15];
3474	CK_BYTE			*keydata = NULL;
3475	int			i = 0;
3476	KMF_KEY_HANDLE		*symkey;
3477	KMF_KEY_ALG		keytype;
3478	uint32_t		keylen = 0;
3479	uint32_t		attrkeylen = 0;
3480	uint32_t		keylen_size = sizeof (uint32_t);
3481	char			*keylabel = NULL;
3482	KMF_CREDENTIAL		*cred = NULL;
3483	uint32_t		is_sensitive = B_FALSE;
3484	uint32_t		is_not_extractable = B_FALSE;
3485
3486	if (kmfh == NULL)
3487		return (KMF_ERR_UNINITIALIZED);
3488
3489	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3490		return (KMF_ERR_NO_TOKEN_SELECTED);
3491
3492	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3493	if (symkey == NULL)
3494		return (KMF_ERR_BAD_PARAMETER);
3495
3496	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
3497	    (void *)&keytype, NULL);
3498	if (rv != KMF_OK)
3499		return (KMF_ERR_BAD_PARAMETER);
3500
3501	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3502	if (keylabel == NULL)
3503		return (KMF_ERR_BAD_PARAMETER);
3504
3505	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3506	    (void *)&is_sensitive, NULL);
3507	if (rv != KMF_OK)
3508		return (KMF_ERR_BAD_PARAMETER);
3509
3510	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3511	    (void *)&is_not_extractable, NULL);
3512	if (rv != KMF_OK)
3513		return (KMF_ERR_BAD_PARAMETER);
3514
3515	/*
3516	 * For AES, RC4, DES and 3DES, call C_GenerateKey() to create a key.
3517	 *
3518	 * For a generic secret key, because it may not be supported in
3519	 * C_GenerateKey() for some PKCS11 providers, we will handle it
3520	 * differently.
3521	 */
3522	if (keytype == KMF_GENERIC_SECRET) {
3523		rv = create_generic_secret_key(handle, numattr,
3524		    attrlist, &keyhandle);
3525		if (rv != KMF_OK)
3526			goto out;
3527		else
3528			goto setup;
3529	}
3530
3531	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3532	    NULL, &attrkeylen);
3533	if (rv == KMF_OK && attrkeylen > 0) {
3534		keydata = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3535		    numattr);
3536	} else {
3537		keydata = NULL;
3538		attrkeylen = 0;
3539		rv = KMF_OK;
3540	}
3541	if (keydata != NULL) {
3542		if (keytype == KMF_DES && attrkeylen != 8) {
3543			rv = KMF_ERR_BAD_KEY_SIZE;
3544			goto out;
3545		}
3546		if (keytype == KMF_DES3 && attrkeylen != 24) {
3547			rv = KMF_ERR_BAD_KEY_SIZE;
3548			goto out;
3549		}
3550		/*
3551		 * This may override what the user gave on the
3552		 * command line.
3553		 */
3554		keylen = attrkeylen * 8; /* bytes to bits */
3555	} else {
3556		/*
3557		 * If keydata was not given, key length must be
3558		 * provided.
3559		 */
3560		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3561		    &keylen, &keylen_size);
3562		if (rv == KMF_ERR_ATTR_NOT_FOUND &&
3563		    (keytype == KMF_DES || keytype == KMF_DES3))
3564			/* keylength is not required for DES and 3DES */
3565			rv = KMF_OK;
3566		if (rv != KMF_OK)
3567			return (KMF_ERR_BAD_PARAMETER);
3568	}
3569
3570	if ((keylen % 8) != 0) {
3571		return (KMF_ERR_BAD_KEY_SIZE);
3572	}
3573	secKeyLen = keylen / 8;  /* in bytes for RC4/AES */
3574
3575	/*
3576	 * Only set CKA_VALUE_LEN if the key data was not given and
3577	 * we are creating an RC4 or AES key.
3578	 */
3579	if (keydata == NULL &&
3580	    (keytype == KMF_AES || keytype == KMF_RC4)) {
3581		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
3582		    sizeof (secKeyLen));
3583		i++;
3584	}
3585
3586	/* Other keytypes */
3587	keyGenMech.pParameter = NULL_PTR;
3588	keyGenMech.ulParameterLen = 0;
3589	switch (keytype) {
3590		case KMF_AES:
3591			keyGenMech.mechanism = CKM_AES_KEY_GEN;
3592			secKeyType = CKK_AES;
3593			break;
3594		case KMF_RC4:
3595			keyGenMech.mechanism = CKM_RC4_KEY_GEN;
3596			secKeyType = CKK_RC4;
3597			break;
3598		case KMF_DES:
3599			keyGenMech.mechanism = CKM_DES_KEY_GEN;
3600			secKeyType = CKK_DES;
3601			break;
3602		case KMF_DES3:
3603			keyGenMech.mechanism = CKM_DES3_KEY_GEN;
3604			secKeyType = CKK_DES3;
3605			break;
3606		default:
3607			return (KMF_ERR_BAD_KEY_TYPE);
3608	}
3609	if (keydata != NULL) {
3610		SETATTR(templ, i, CKA_VALUE, keydata, secKeyLen);
3611		i++;
3612	}
3613	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3614	i++;
3615	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3616	i++;
3617
3618	if (keylabel != NULL) {
3619		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3620		i++;
3621	}
3622
3623	if (is_sensitive == B_TRUE) {
3624		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3625	} else {
3626		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3627	}
3628	i++;
3629
3630	if (is_not_extractable == B_TRUE) {
3631		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3632	} else {
3633		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3634	}
3635	i++;
3636
3637	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3638	i++;
3639	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3640	i++;
3641	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
3642	i++;
3643	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
3644	i++;
3645	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3646	i++;
3647	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
3648	i++;
3649
3650	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3651	if (cred == NULL)
3652		return (KMF_ERR_BAD_PARAMETER);
3653
3654	rv = pk11_authenticate(handle, cred);
3655	if (rv != KMF_OK) {
3656		return (rv);
3657	}
3658
3659	/* If the key data was given, use C_CreateObject */
3660	if (keydata != NULL) {
3661		ckrv = C_CreateObject(hSession, templ, i, &keyhandle);
3662	} else {
3663		ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i,
3664		    &keyhandle);
3665	}
3666	if (ckrv != CKR_OK) {
3667		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3668		    ckrv == CKR_PIN_INCORRECT ||
3669		    ckrv == CKR_PIN_INVALID ||
3670		    ckrv == CKR_PIN_EXPIRED ||
3671		    ckrv == CKR_PIN_LOCKED ||
3672		    ckrv == CKR_SESSION_READ_ONLY)
3673			rv = KMF_ERR_AUTH_FAILED;
3674		else
3675			rv = KMF_ERR_KEYGEN_FAILED;
3676		SET_ERROR(kmfh, ckrv);
3677		goto out;
3678	}
3679
3680setup:
3681	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
3682	symkey->keyalg = keytype;
3683	symkey->keyclass = KMF_SYMMETRIC;
3684	symkey->israw = FALSE;
3685	symkey->keyp = (void *)keyhandle;
3686
3687out:
3688	return (rv);
3689}
3690
3691KMF_RETURN
3692KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
3693    KMF_RAW_SYM_KEY *rkey)
3694{
3695	KMF_RETURN		rv = KMF_OK;
3696	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3697
3698	if (kmfh == NULL)
3699		return (KMF_ERR_UNINITIALIZED);
3700
3701	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3702		return (KMF_ERR_NO_TOKEN_SELECTED);
3703
3704	if (symkey == NULL || rkey == NULL)
3705		return (KMF_ERR_BAD_PARAMETER);
3706	else if (symkey->keyclass != KMF_SYMMETRIC)
3707		return (KMF_ERR_BAD_KEY_CLASS);
3708
3709	/*
3710	 * If the key is already in "raw" format, copy the data
3711	 * to the new record if possible.
3712	 */
3713	if (symkey->israw) {
3714		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
3715
3716		if (rawkey == NULL)
3717			return (KMF_ERR_BAD_KEYHANDLE);
3718		if (rawkey->sensitive)
3719			return (KMF_ERR_SENSITIVE_KEY);
3720		if (rawkey->not_extractable)
3721			return (KMF_ERR_UNEXTRACTABLE_KEY);
3722
3723		if (rawkey->rawdata.sym.keydata.val == NULL ||
3724		    rawkey->rawdata.sym.keydata.len == 0)
3725			return (KMF_ERR_GETKEYVALUE_FAILED);
3726
3727		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
3728		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
3729			return (KMF_ERR_MEMORY);
3730		(void) memcpy(rkey->keydata.val,
3731		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
3732	} else {
3733		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
3734	}
3735
3736	return (rv);
3737}
3738
3739KMF_RETURN
3740KMFPK11_SetTokenPin(KMF_HANDLE_T handle,
3741	int numattr, KMF_ATTRIBUTE *attrlist)
3742{
3743	KMF_RETURN	ret = KMF_OK;
3744	CK_RV		rv = CKR_OK;
3745	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3746	CK_SESSION_HANDLE	session = NULL;
3747	KMF_CREDENTIAL	*oldcred;
3748	KMF_CREDENTIAL	*newcred;
3749	CK_SLOT_ID	slotid;
3750	CK_USER_TYPE	user = CKU_USER;
3751
3752	if (handle == NULL || attrlist == NULL || numattr == 0)
3753		return (KMF_ERR_BAD_PARAMETER);
3754
3755	oldcred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3756	if (oldcred == NULL)
3757		return (KMF_ERR_BAD_PARAMETER);
3758
3759	newcred = kmf_get_attr_ptr(KMF_NEWPIN_ATTR, attrlist, numattr);
3760	if (newcred == NULL)
3761		return (KMF_ERR_BAD_PARAMETER);
3762
3763	rv = kmf_get_attr(KMF_SLOT_ID_ATTR, attrlist, numattr,
3764	    (void *)&slotid, NULL);
3765	if (rv != KMF_OK) {
3766		char *tokenlabel = NULL;
3767		/*
3768		 * If a slot wasn't given, the user must pass
3769		 * a token label so we can find the slot here.
3770		 */
3771		tokenlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
3772		    numattr);
3773		if (tokenlabel == NULL)
3774			return (KMF_ERR_BAD_PARAMETER);
3775
3776		rv = kmf_pk11_token_lookup(handle, tokenlabel, &slotid);
3777		if (rv != KMF_OK)
3778			return (rv);
3779	}
3780	rv = kmf_get_attr(KMF_PK11_USER_TYPE_ATTR, attrlist, numattr,
3781	    (void *)&user, NULL);
3782	if (rv != CKR_OK)
3783		user = CKU_USER;
3784
3785	rv = C_OpenSession(slotid, CKF_SERIAL_SESSION | CKF_RW_SESSION,
3786	    NULL, NULL, &session);
3787	if (rv != CKR_OK) {
3788		SET_ERROR(kmfh, rv);
3789		ret = KMF_ERR_UNINITIALIZED;
3790		goto end;
3791	}
3792
3793	rv = C_Login(session, user, (CK_BYTE *)oldcred->cred,
3794	    oldcred->credlen);
3795	if (rv != CKR_OK) {
3796		SET_ERROR(kmfh, rv);
3797		if (rv == CKR_PIN_INCORRECT ||
3798		    rv == CKR_PIN_INVALID ||
3799		    rv == CKR_PIN_EXPIRED ||
3800		    rv == CKR_PIN_LOCKED)
3801			ret = KMF_ERR_AUTH_FAILED;
3802		else
3803			ret = KMF_ERR_INTERNAL;
3804
3805		goto end;
3806	}
3807
3808	rv = C_SetPIN(session,
3809	    (CK_BYTE *)oldcred->cred, oldcred->credlen,
3810	    (CK_BYTE *)newcred->cred, newcred->credlen);
3811
3812	if (rv != CKR_OK) {
3813		SET_ERROR(kmfh, rv);
3814		if (rv == CKR_PIN_INCORRECT ||
3815		    rv == CKR_PIN_INVALID ||
3816		    rv == CKR_PIN_EXPIRED ||
3817		    rv == CKR_PIN_LOCKED)
3818			ret = KMF_ERR_AUTH_FAILED;
3819		else
3820			ret = KMF_ERR_INTERNAL;
3821	}
3822end:
3823	if (session != NULL)
3824		(void) C_CloseSession(session);
3825	return (ret);
3826}
3827
3828static KMF_RETURN
3829create_generic_secret_key(KMF_HANDLE_T handle,
3830	int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key)
3831{
3832	KMF_RETURN		rv = KMF_OK;
3833	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3834	CK_RV			ckrv;
3835	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3836	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3837	CK_ULONG		secKeyType = CKK_GENERIC_SECRET;
3838	CK_ULONG		secKeyLen;
3839	CK_BBOOL		true = TRUE;
3840	CK_BBOOL		false = FALSE;
3841	CK_ATTRIBUTE		templ[15];
3842	int			i;
3843	int			random_fd = -1;
3844	int			nread;
3845	int			freebuf = 0;
3846	char			*buf = NULL;
3847	uint32_t		keylen = 0, attrkeylen = 0;
3848	char			*keylabel = NULL;
3849	KMF_CREDENTIAL		*cred;
3850	uint32_t is_sensitive, is_not_extractable;
3851
3852	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3853	if (keylabel == NULL)
3854		return (KMF_ERR_BAD_PARAMETER);
3855
3856	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3857	if (cred == NULL)
3858		return (KMF_ERR_BAD_PARAMETER);
3859
3860	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3861	    (void *)&is_sensitive, NULL);
3862	if (rv != KMF_OK)
3863		return (KMF_ERR_BAD_PARAMETER);
3864
3865	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3866	    (void *)&is_not_extractable, NULL);
3867	if (rv != KMF_OK)
3868		return (KMF_ERR_BAD_PARAMETER);
3869
3870	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3871	    NULL, &attrkeylen);
3872	if (rv == KMF_OK && attrkeylen > 0) {
3873		buf = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3874		    numattr);
3875		secKeyLen = attrkeylen;
3876	} else {
3877		buf = NULL;
3878		rv = KMF_OK;
3879	}
3880	if (buf == NULL) {
3881		/*
3882		 * If the key data was not given, key length must
3883		 * be provided.
3884		 */
3885		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3886		    &keylen, NULL);
3887		if (rv != KMF_OK)
3888			return (KMF_ERR_BAD_PARAMETER);
3889
3890		/*
3891		 * Check the key size.
3892		 */
3893		if ((keylen % 8) != 0) {
3894			return (KMF_ERR_BAD_KEY_SIZE);
3895		} else {
3896			secKeyLen = keylen/8;  /* in bytes */
3897		}
3898
3899		/*
3900		 * Generate a random number with the key size first.
3901		 */
3902		buf = malloc(secKeyLen);
3903		if (buf == NULL)
3904			return (KMF_ERR_MEMORY);
3905
3906		freebuf = 1;
3907		while ((random_fd = open(DEV_RANDOM, O_RDONLY)) < 0) {
3908			if (errno != EINTR)
3909				break;
3910		}
3911
3912		if (random_fd < 0) {
3913			rv = KMF_ERR_KEYGEN_FAILED;
3914			goto out;
3915		}
3916
3917		nread = read(random_fd, buf, secKeyLen);
3918		if (nread <= 0 || nread != secKeyLen) {
3919			rv = KMF_ERR_KEYGEN_FAILED;
3920			goto out;
3921		}
3922	}
3923
3924	/*
3925	 * Authenticate into the token and call C_CreateObject to generate
3926	 * a generic secret token key.
3927	 */
3928	rv = pk11_authenticate(handle, cred);
3929	if (rv != KMF_OK) {
3930		goto out;
3931	}
3932
3933	i = 0;
3934	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3935	i++;
3936	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3937	i++;
3938	SETATTR(templ, i, CKA_VALUE, buf, secKeyLen);
3939	i++;
3940
3941	if (keylabel != NULL) {
3942		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3943		i++;
3944	}
3945
3946	if (is_sensitive == B_TRUE) {
3947		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3948	} else {
3949		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3950	}
3951	i++;
3952
3953	if (is_not_extractable == B_TRUE) {
3954		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3955	} else {
3956		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3957	}
3958	i++;
3959
3960	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3961	i++;
3962	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3963	i++;
3964	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3965	i++;
3966
3967	ckrv = C_CreateObject(hSession, templ, i, key);
3968	if (ckrv != CKR_OK) {
3969		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3970		    ckrv == CKR_PIN_INCORRECT ||
3971		    ckrv == CKR_PIN_INVALID ||
3972		    ckrv == CKR_PIN_EXPIRED ||
3973		    ckrv == CKR_PIN_LOCKED ||
3974		    ckrv == CKR_SESSION_READ_ONLY)
3975			rv = KMF_ERR_AUTH_FAILED;
3976		else
3977			rv = KMF_ERR_KEYGEN_FAILED;
3978		SET_ERROR(kmfh, ckrv);
3979	}
3980
3981out:
3982	if (buf != NULL && freebuf)
3983		free(buf);
3984
3985	if (random_fd != -1)
3986		(void) close(random_fd);
3987
3988	return (rv);
3989}
3990
3991KMF_RETURN
3992KMFPK11_StoreKey(KMF_HANDLE_T handle,
3993	int numattr,
3994	KMF_ATTRIBUTE *attlist)
3995{
3996	KMF_RETURN rv = KMF_OK;
3997	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3998	KMF_CREDENTIAL cred = {NULL, 0};
3999	KMF_KEY_HANDLE *key;
4000	KMF_RAW_KEY_DATA *rawkey = NULL;
4001	CK_BBOOL btrue = TRUE;
4002	CK_ATTRIBUTE tokenattr[1];
4003	CK_OBJECT_HANDLE newobj;
4004	CK_RV ckrv;
4005
4006	if (kmfh == NULL)
4007		return (KMF_ERR_UNINITIALIZED);
4008
4009	if (kmfh->pk11handle == CK_INVALID_HANDLE)
4010		return (KMF_ERR_NO_TOKEN_SELECTED);
4011
4012	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attlist, numattr,
4013	    (void *)&cred, NULL);
4014	if (rv != KMF_OK)
4015		return (KMF_ERR_BAD_PARAMETER);
4016
4017	rv = pk11_authenticate(handle, &cred);
4018	if (rv != KMF_OK)
4019		return (rv);
4020
4021	key = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
4022	if (key == NULL) {
4023		key = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist,
4024		    numattr);
4025		if (key == NULL)
4026			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attlist,
4027			    numattr);
4028	}
4029	if (key == NULL && rawkey == NULL)
4030		return (KMF_ERR_ATTR_NOT_FOUND);
4031
4032	if (rawkey != NULL) {
4033		rv = store_raw_key(handle, attlist, numattr, rawkey);
4034	} else if (key && key->kstype == KMF_KEYSTORE_PK11TOKEN) {
4035
4036		SETATTR(tokenattr, 0, CKA_TOKEN, &btrue, sizeof (btrue));
4037		/* Copy the key object to the token */
4038		ckrv = C_CopyObject(kmfh->pk11handle,
4039		    (CK_OBJECT_HANDLE)key->keyp, tokenattr, 1, &newobj);
4040		if (ckrv != CKR_OK)  {
4041			SET_ERROR(kmfh, ckrv);
4042			return (KMF_ERR_INTERNAL);
4043		}
4044
4045		/* Replace the object handle with the new token-based one */
4046		ckrv = C_DestroyObject(kmfh->pk11handle,
4047		    (CK_OBJECT_HANDLE)key->keyp);
4048		if (ckrv != CKR_OK)  {
4049			SET_ERROR(kmfh, ckrv);
4050			return (KMF_ERR_INTERNAL);
4051		}
4052		key->keyp = (void *)newobj;
4053	} else {
4054		rv = KMF_ERR_BAD_PARAMETER;
4055	}
4056
4057	return (rv);
4058}
4059
4060
4061KMF_RETURN
4062KMFPK11_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4063{
4064	KMF_RETURN rv = KMF_OK;
4065	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4066	KMF_CREDENTIAL *cred = NULL;
4067	KMF_CREDENTIAL *p12cred = NULL;
4068	char *filename = NULL;
4069	KMF_X509_DER_CERT *certlist = NULL;
4070	KMF_KEY_HANDLE *keylist = NULL;
4071	uint32_t numcerts;
4072	uint32_t numkeys;
4073	char *certlabel = NULL;
4074	char *issuer = NULL;
4075	char *subject = NULL;
4076	KMF_BIGINT *serial = NULL;
4077	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
4078	KMF_ATTRIBUTE fc_attrlist[16];
4079	int i;
4080
4081	if (kmfh == NULL)
4082		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
4083
4084	if (kmfh->pk11handle == CK_INVALID_HANDLE)
4085		return (KMF_ERR_NO_TOKEN_SELECTED);
4086
4087	/* First get the required attributes */
4088	cred =  kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
4089	if (cred == NULL)
4090		return (KMF_ERR_BAD_PARAMETER);
4091
4092	p12cred =  kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
4093	if (p12cred == NULL)
4094		return (KMF_ERR_BAD_PARAMETER);
4095
4096	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
4097	    numattr);
4098	if (filename == NULL)
4099		return (KMF_ERR_BAD_PARAMETER);
4100
4101	/* Find all the certificates that match the searching criteria */
4102	i = 0;
4103	kmf_set_attr_at_index(fc_attrlist, i,
4104	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
4105	i++;
4106
4107	kmf_set_attr_at_index(fc_attrlist, i,
4108	    KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
4109	i++;
4110
4111	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
4112	if (certlabel != NULL) {
4113		kmf_set_attr_at_index(fc_attrlist, i,
4114		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
4115		i++;
4116	}
4117
4118	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
4119	if (issuer != NULL) {
4120		kmf_set_attr_at_index(fc_attrlist, i,
4121		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
4122		i++;
4123	}
4124
4125	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
4126	if (subject != NULL) {
4127		kmf_set_attr_at_index(fc_attrlist, i,
4128		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
4129		i++;
4130	}
4131
4132	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
4133	if (serial != NULL) {
4134		kmf_set_attr_at_index(fc_attrlist, i,
4135		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
4136		i++;
4137	}
4138
4139	rv = KMFPK11_FindCert(handle, i, fc_attrlist);
4140
4141	if (rv == KMF_OK && numcerts > 0) {
4142		certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
4143		    sizeof (KMF_X509_DER_CERT));
4144		if (certlist == NULL)
4145			return (KMF_ERR_MEMORY);
4146
4147		(void) memset(certlist, 0, numcerts *
4148		    sizeof (KMF_X509_DER_CERT));
4149
4150		kmf_set_attr_at_index(fc_attrlist, i, KMF_X509_DER_CERT_ATTR,
4151		    certlist, sizeof (KMF_X509_DER_CERT));
4152		i++;
4153
4154		rv = kmf_find_cert(handle, i, fc_attrlist);
4155		if (rv != KMF_OK) {
4156			free(certlist);
4157			return (rv);
4158		}
4159	} else {
4160		return (rv);
4161	}
4162
4163	/* For each certificate, find the matching private key */
4164	numkeys = 0;
4165	for (i = 0; i < numcerts; i++) {
4166		KMF_ATTRIBUTE fk_attrlist[16];
4167		int j = 0;
4168		KMF_KEY_HANDLE newkey;
4169		KMF_ENCODE_FORMAT format = KMF_FORMAT_RAWKEY;
4170
4171		kmf_set_attr_at_index(fk_attrlist, j,
4172		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
4173		j++;
4174
4175		kmf_set_attr_at_index(fk_attrlist, j,
4176		    KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
4177		j++;
4178
4179		kmf_set_attr_at_index(fk_attrlist, j,
4180		    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
4181		j++;
4182
4183		kmf_set_attr_at_index(fk_attrlist, j,
4184		    KMF_CERT_DATA_ATTR, &certlist[i].certificate,
4185		    sizeof (KMF_DATA));
4186		j++;
4187
4188		kmf_set_attr_at_index(fk_attrlist, j,
4189		    KMF_KEY_HANDLE_ATTR, &newkey, sizeof (KMF_KEY_HANDLE));
4190		j++;
4191
4192		rv = KMFPK11_FindPrikeyByCert(handle, j, fk_attrlist);
4193		if (rv == KMF_OK) {
4194			numkeys++;
4195			keylist = realloc(keylist,
4196			    numkeys * sizeof (KMF_KEY_HANDLE));
4197			if (keylist == NULL) {
4198				rv = KMF_ERR_MEMORY;
4199				goto out;
4200			}
4201			keylist[numkeys - 1] = newkey;
4202		} else if (rv == KMF_ERR_KEY_NOT_FOUND) {
4203			/* it is OK if a key is not found */
4204			rv = KMF_OK;
4205		}
4206	}
4207
4208	if (rv != KMF_OK)
4209		goto out;
4210
4211	rv = kmf_build_pk12(handle, numcerts, certlist, numkeys, keylist,
4212	    p12cred, filename);
4213
4214out:
4215	if (certlist != NULL) {
4216		for (i = 0; i < numcerts; i++)
4217			kmf_free_kmf_cert(handle, &certlist[i]);
4218		free(certlist);
4219	}
4220	if (keylist != NULL) {
4221		for (i = 0; i < numkeys; i++)
4222			kmf_free_kmf_key(handle, &keylist[i]);
4223		free(keylist);
4224	}
4225
4226	return (rv);
4227}
4228