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