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