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