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