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