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