xref: /onnv-gate/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c (revision 3754:79eeec53e95c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * PKCS11 token KMF Plugin
23  *
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <stdio.h> /* debugging only */
31 #include <errno.h>
32 #include <values.h>
33 
34 #include <kmfapiP.h>
35 #include <ber_der.h>
36 #include <algorithm.h>
37 
38 #include <cryptoutil.h>
39 #include <security/cryptoki.h>
40 #include <security/pkcs11.h>
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 KMF_RETURN
66 KMFPK11_ConfigureKeystore(KMF_HANDLE_T, KMF_CONFIG_PARAMS *);
67 
68 KMF_RETURN
69 KMFPK11_FindCert(KMF_HANDLE_T,
70 	KMF_FINDCERT_PARAMS *,
71 	KMF_X509_DER_CERT *,
72 	uint32_t *);
73 
74 void
75 KMFPK11_FreeKMFCert(KMF_HANDLE_T,
76 	KMF_X509_DER_CERT *kmf_cert);
77 
78 KMF_RETURN
79 KMFPK11_StoreCert(KMF_HANDLE_T, KMF_STORECERT_PARAMS *, KMF_DATA *);
80 
81 KMF_RETURN
82 KMFPK11_ImportCert(KMF_HANDLE_T, KMF_IMPORTCERT_PARAMS *);
83 
84 KMF_RETURN
85 KMFPK11_DeleteCert(KMF_HANDLE_T, KMF_DELETECERT_PARAMS *);
86 
87 KMF_RETURN
88 KMFPK11_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
89 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
90 
91 KMF_RETURN
92 KMFPK11_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
93 	KMF_KEY_HANDLE *, boolean_t);
94 
95 KMF_RETURN
96 KMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
97 
98 KMF_RETURN
99 KMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
100 	KMF_DATA *, KMF_DATA *);
101 
102 KMF_RETURN
103 KMFPK11_GetErrorString(KMF_HANDLE_T, char **);
104 
105 KMF_RETURN
106 KMFPK11_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
107 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
108 
109 KMF_RETURN
110 KMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
111 	KMF_DATA *, KMF_DATA *);
112 
113 KMF_RETURN
114 KMFPK11_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
115 	KMF_KEY_HANDLE *, uint32_t *);
116 
117 KMF_RETURN
118 KMFPK11_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
119 	KMF_RAW_KEY_DATA *);
120 
121 KMF_RETURN
122 KMFPK11_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
123 	KMF_KEY_HANDLE *);
124 
125 KMF_RETURN
126 KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127 
128 KMF_RETURN
129 KMFPK11_SetTokenPin(KMF_HANDLE_T, KMF_SETPIN_PARAMS *, KMF_CREDENTIAL *);
130 
131 KMF_RETURN
132 KMFPK11_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, KMF_DATA *,
133 	KMF_DATA *, KMF_DATA *);
134 
135 static
136 KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
137 {
138 	1,			/* Version */
139 	KMFPK11_ConfigureKeystore,
140 	KMFPK11_FindCert,
141 	KMFPK11_FreeKMFCert,
142 	KMFPK11_StoreCert,
143 	KMFPK11_ImportCert,
144 	NULL,			/* ImportCRL */
145 	KMFPK11_DeleteCert,
146 	NULL,			/* DeleteCRL */
147 	KMFPK11_CreateKeypair,
148 	KMFPK11_FindKey,
149 	KMFPK11_EncodePubKeyData,
150 	KMFPK11_SignData,
151 	KMFPK11_DeleteKey,
152 	NULL,			/* ListCRL */
153 	NULL,			/* FindCRL */
154 	NULL,			/* FindCertInCRL */
155 	KMFPK11_GetErrorString,
156 	KMFPK11_GetPrikeyByCert,
157 	KMFPK11_DecryptData,
158 	NULL,			/* ExportP12 */
159 	KMFPK11_StorePrivateKey,
160 	KMFPK11_CreateSymKey,
161 	KMFPK11_GetSymKeyValue,
162 	KMFPK11_SetTokenPin,
163 	KMFPK11_VerifyDataWithCert,
164 	NULL			/* Finalize */
165 };
166 
167 KMF_PLUGIN_FUNCLIST *
168 KMF_Plugin_Initialize()
169 {
170 	return (&pk11token_plugin_table);
171 }
172 
173 KMF_RETURN
174 KMFPK11_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
175 {
176 	KMF_RETURN rv = KMF_OK;
177 
178 	if (params == NULL || params->pkcs11config.label == NULL)
179 		return (KMF_ERR_BAD_PARAMETER);
180 
181 	rv = KMF_SelectToken(handle, params->pkcs11config.label,
182 	    params->pkcs11config.readonly);
183 
184 	return (rv);
185 }
186 
187 static KMF_RETURN
188 pk11_authenticate(KMF_HANDLE_T handle,
189 	KMF_CREDENTIAL *cred)
190 {
191 
192 	CK_RV ck_rv = CKR_OK;
193 	CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
194 
195 	if (hSession == NULL)
196 		return (KMF_ERR_NO_TOKEN_SELECTED);
197 
198 	if (cred == NULL || cred->cred == NULL || cred->credlen == 0) {
199 		return (KMF_ERR_BAD_PARAMETER);
200 	}
201 
202 	if ((ck_rv = C_Login(hSession, CKU_USER,
203 		(uchar_t *)cred->cred, cred->credlen)) != CKR_OK) {
204 		if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
205 			handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
206 			handle->lasterr.errcode = ck_rv;
207 			return (KMF_ERR_AUTH_FAILED);
208 		}
209 	}
210 
211 	return (KMF_OK);
212 }
213 
214 static KMF_RETURN
215 PK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
216 		KMF_X509_DER_CERT *kmfcert)
217 {
218 	KMF_RETURN rv = 0;
219 	CK_RV ckrv = CKR_OK;
220 
221 	CK_CERTIFICATE_TYPE cktype;
222 	CK_OBJECT_CLASS	class;
223 	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
224 	CK_BYTE *subject = NULL, *value = NULL;
225 	char *label = NULL;
226 	CK_ATTRIBUTE templ[10];
227 
228 	(void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
229 	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
230 
231 	/*  Is this a certificate object ? */
232 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
233 	if (ckrv != CKR_OK || class != CKO_CERTIFICATE)  {
234 		SET_ERROR(kmfh, ckrv);
235 		return (KMF_ERR_INTERNAL);
236 	}
237 
238 	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
239 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
240 
241 	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
242 		SET_ERROR(kmfh, ckrv);
243 		return (ckrv);
244 	} else {
245 		int i = 0;
246 		/* What attributes are available and how big are they? */
247 		subject_len = issuer_len = serno_len = id_len = value_len = 0;
248 
249 		SETATTR(templ, i, CKA_SUBJECT,	NULL, subject_len);
250 		i++;
251 		SETATTR(templ, i, CKA_ISSUER,	NULL, issuer_len);
252 		i++;
253 		SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
254 		i++;
255 		SETATTR(templ, i, CKA_ID, NULL, id_len);
256 		i++;
257 		SETATTR(templ, i, CKA_VALUE, NULL, value_len);
258 		i++;
259 
260 		/*
261 		 * Query the object with NULL values in the pValue spot
262 		 * so we know how much space to allocate for each field.
263 		 */
264 		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
265 		if (ckrv != CKR_OK)  {
266 			SET_ERROR(kmfh, ckrv);
267 			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
268 		}
269 
270 		subject_len	= templ[0].ulValueLen;
271 		issuer_len	= templ[1].ulValueLen;
272 		serno_len	= templ[2].ulValueLen;
273 		id_len		= templ[3].ulValueLen;
274 		value_len	= templ[4].ulValueLen;
275 
276 		/*
277 		 * For PKCS#11 CKC_X_509 certificate objects,
278 		 * the following attributes must be defined.
279 		 * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
280 		 * CKA_VALUE.
281 		 */
282 		if (subject_len == 0 || issuer_len == 0 ||
283 		    serno_len == 0 || value_len == 0) {
284 			return (KMF_ERR_INTERNAL);
285 		}
286 
287 		/* Only fetch the value field if we are saving the data */
288 		if (kmfcert != NULL) {
289 			int i = 0;
290 			value = malloc(value_len);
291 			if (value == NULL) {
292 				rv = KMF_ERR_MEMORY;
293 				goto errout;
294 			}
295 
296 			SETATTR(templ, i, CKA_VALUE, value, value_len);
297 			i++;
298 
299 			/* re-query the object with room for the value attr */
300 			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
301 				templ, i);
302 
303 			if (ckrv != CKR_OK)  {
304 				SET_ERROR(kmfh, ckrv);
305 				rv = KMF_ERR_INTERNAL;
306 				goto errout;
307 			}
308 
309 			kmfcert->certificate.Data = value;
310 			kmfcert->certificate.Length = value_len;
311 			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
312 			kmfcert->kmf_private.keystore_type =
313 				KMF_KEYSTORE_PK11TOKEN;
314 
315 			ckrv = getObjectLabel(kmfh, hObj, &label);
316 			if (ckrv == CKR_OK && label != NULL) {
317 				kmfcert->kmf_private.label = (char *)label;
318 			}
319 
320 			rv = KMF_OK;
321 		}
322 	}
323 
324 errout:
325 	if (rv != KMF_OK) {
326 		if (subject)
327 			free(subject);
328 		if (value)
329 			free(value);
330 
331 		if (kmfcert) {
332 			kmfcert->certificate.Data = NULL;
333 			kmfcert->certificate.Length = 0;
334 		}
335 	}
336 	return (rv);
337 }
338 
339 static void
340 free_objlist(OBJLIST *head)
341 {
342 	OBJLIST *temp = head;
343 
344 	while (temp != NULL) {
345 		head = head->next;
346 		free(temp);
347 		temp = head;
348 	}
349 }
350 
351 /*
352  * The caller should make sure that the templ->pValue is NULL since
353  * it will be overwritten below.
354  */
355 static KMF_RETURN
356 get_attr(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
357 	CK_ATTRIBUTE *templ)
358 {
359 	CK_RV rv;
360 
361 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
362 	if (rv != CKR_OK) {
363 		SET_ERROR(kmfh, rv);
364 		return (KMF_ERR_INTERNAL);
365 	}
366 
367 	if (templ->ulValueLen > 0) {
368 		templ->pValue = malloc(templ->ulValueLen);
369 		if (templ->pValue == NULL)
370 			return (KMF_ERR_MEMORY);
371 
372 		rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
373 		if (rv != CKR_OK) {
374 			SET_ERROR(kmfh, rv);
375 			return (KMF_ERR_INTERNAL);
376 		}
377 	}
378 
379 	return (KMF_OK);
380 }
381 
382 /*
383  * Match a certificate with an issuer and/or subject name.
384  * This is tricky because we cannot reliably compare DER encodings
385  * because RDNs may have their AV-pairs in different orders even
386  * if the values are the same.  You must compare individual
387  * AV pairs for the RDNs.
388  *
389  * RETURN: 0 for a match, non-zero for a non-match.
390  */
391 static KMF_RETURN
392 matchcert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
393 	KMF_X509_NAME *issuer, KMF_X509_NAME *subject)
394 {
395 	KMF_RETURN rv = KMF_OK;
396 	CK_ATTRIBUTE certattr;
397 	KMF_DATA name;
398 	KMF_X509_NAME dn;
399 
400 	if (issuer->numberOfRDNs > 0) {
401 		certattr.type = CKA_ISSUER;
402 		certattr.pValue = NULL;
403 		certattr.ulValueLen = 0;
404 
405 		rv = get_attr(kmfh, obj, &certattr);
406 
407 		if (rv == KMF_OK) {
408 			name.Data = certattr.pValue;
409 			name.Length = certattr.ulValueLen;
410 			rv = DerDecodeName(&name, &dn);
411 			if (rv == KMF_OK) {
412 				rv = KMF_CompareRDNs(issuer, &dn);
413 				KMF_FreeDN(&dn);
414 			}
415 			free(certattr.pValue);
416 		}
417 
418 		if (rv != KMF_OK)
419 			return (rv);
420 	}
421 	if (subject->numberOfRDNs > 0) {
422 		certattr.type = CKA_SUBJECT;
423 		certattr.pValue = NULL;
424 		certattr.ulValueLen = 0;
425 
426 		rv = get_attr(kmfh, obj, &certattr);
427 
428 		if (rv == KMF_OK) {
429 			name.Data = certattr.pValue;
430 			name.Length = certattr.ulValueLen;
431 			rv = DerDecodeName(&name, &dn);
432 			if (rv == KMF_OK) {
433 				rv = KMF_CompareRDNs(subject, &dn);
434 				KMF_FreeDN(&dn);
435 			}
436 			free(certattr.pValue);
437 		}
438 	}
439 
440 	return (rv);
441 }
442 
443 /*
444  * delete "curr" node from the "newlist".
445  */
446 static void
447 pk11_delete_obj_from_list(OBJLIST **newlist,
448 	OBJLIST **prev, OBJLIST **curr)
449 {
450 
451 	if (*curr == *newlist) {
452 		/* first node in the list */
453 		*newlist = (*curr)->next;
454 		*prev = (*curr)->next;
455 		free(*curr);
456 		*curr = *newlist;
457 	} else {
458 		(*prev)->next = (*curr)->next;
459 		free(*curr);
460 		*curr = (*prev)->next;
461 	}
462 }
463 
464 /*
465  * prepare_object_search
466  *
467  * Because this code is shared by the FindCert and
468  * DeleteCert functions, put it in a separate routine
469  * to save some work and make code easier to debug and
470  * read.
471  */
472 static KMF_RETURN
473 search_certs(KMF_HANDLE_T handle,
474 	char *label, char *issuer, char *subject, KMF_BIGINT *serial,
475 	boolean_t private, KMF_CERT_VALIDITY validity,
476 	OBJLIST **objlist, uint32_t *numobj)
477 {
478 	KMF_RETURN rv = KMF_OK;
479 	CK_RV ckrv = CKR_OK;
480 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
481 	CK_ATTRIBUTE templ[10];
482 	CK_BBOOL true = TRUE;
483 	CK_OBJECT_CLASS	oclass = CKO_CERTIFICATE;
484 	CK_CERTIFICATE_TYPE ctype = CKC_X_509;
485 	KMF_X509_NAME subjectDN, issuerDN;
486 	int i;
487 	OBJLIST *newlist, *tail;
488 	CK_ULONG num = 0;
489 	uint32_t num_ok_certs = 0; /* number of non-expired or expired certs */
490 
491 	(void) memset(&templ, 0, 10 * sizeof (CK_ATTRIBUTE));
492 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
493 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
494 	i = 0;
495 	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
496 	SETATTR(templ, i, CKA_CLASS, &oclass, sizeof (oclass)); i++;
497 	SETATTR(templ, i, CKA_CERTIFICATE_TYPE, &ctype,
498 		sizeof (ctype)); i++;
499 
500 	if (label != NULL && strlen(label)) {
501 		SETATTR(templ, i, CKA_LABEL, label, strlen(label));
502 		i++;
503 	}
504 	if (private) {
505 		SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true)); i++;
506 	}
507 
508 	if (issuer != NULL && strlen(issuer)) {
509 		if ((rv = KMF_DNParser(issuer, &issuerDN)) != KMF_OK)
510 			return (rv);
511 	}
512 	if (subject != NULL && strlen(subject)) {
513 		if ((rv = KMF_DNParser(subject, &subjectDN)) != KMF_OK)
514 			return (rv);
515 	}
516 
517 	if (serial != NULL && serial->val != NULL && serial->len > 0) {
518 		SETATTR(templ, i, CKA_SERIAL_NUMBER,
519 			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_CheckCertDate(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_FreeKMFCert(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_FreeDN(&issuerDN);
654 
655 	if (subject != NULL)
656 		KMF_FreeDN(&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, KMF_FINDCERT_PARAMS *params,
667 	KMF_X509_DER_CERT *kmf_cert,
668 	uint32_t *num_certs)
669 {
670 	KMF_RETURN rv = 0;
671 	uint32_t want_certs;
672 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
673 	OBJLIST *objlist = NULL;
674 
675 	if (!kmfh)
676 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
677 
678 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
679 		return (KMF_ERR_NO_TOKEN_SELECTED);
680 
681 	if (params == NULL || num_certs == NULL)
682 		return (KMF_ERR_BAD_PARAMETER);
683 
684 	if (*num_certs > 0)
685 		want_certs = *num_certs;
686 	else
687 		want_certs = MAXINT; /* count them all */
688 
689 	*num_certs = 0;
690 
691 	rv = search_certs(handle,
692 		params->certLabel, params->issuer,
693 		params->subject, params->serial,
694 		params->pkcs11parms.private,
695 		params->find_cert_validity,
696 		&objlist, num_certs);
697 
698 	if (rv == KMF_OK && objlist != NULL && kmf_cert != NULL) {
699 		OBJLIST *node = objlist;
700 		int i = 0;
701 		while (node != NULL && i < want_certs) {
702 			rv = PK11Cert2KMFCert(kmfh, node->handle,
703 				&kmf_cert[i]);
704 			i++;
705 			node = node->next;
706 		}
707 	}
708 
709 	if (objlist != NULL)
710 		free_objlist(objlist);
711 
712 	if (*num_certs == 0)
713 		rv = KMF_ERR_CERT_NOT_FOUND;
714 
715 	return (rv);
716 }
717 
718 /*ARGSUSED*/
719 void
720 KMFPK11_FreeKMFCert(KMF_HANDLE_T handle,
721 	KMF_X509_DER_CERT *kmf_cert)
722 {
723 	if (kmf_cert != NULL && kmf_cert->certificate.Data != NULL) {
724 		free(kmf_cert->certificate.Data);
725 		kmf_cert->certificate.Data = NULL;
726 		kmf_cert->certificate.Length = 0;
727 
728 		if (kmf_cert->kmf_private.label != NULL) {
729 			free(kmf_cert->kmf_private.label);
730 			kmf_cert->kmf_private.label = NULL;
731 		}
732 	}
733 }
734 
735 KMF_RETURN
736 KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
737 		KMF_DATA *eData)
738 {
739 	KMF_RETURN ret = KMF_OK;
740 	CK_RV rv;
741 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
742 	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
743 	CK_KEY_TYPE ckKeyType;
744 	KMF_DATA Modulus, Exponent, Prime, Subprime, Base, Value;
745 	KMF_OID *Algorithm;
746 	BerElement *asn1 = NULL;
747 	BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
748 	KMF_X509_SPKI spki;
749 
750 	CK_ATTRIBUTE rsaTemplate[4];
751 	CK_ATTRIBUTE dsaTemplate[6];
752 
753 	if (!kmfh)
754 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
755 
756 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
757 		return (KMF_ERR_NO_TOKEN_SELECTED);
758 
759 	if (pKey == NULL || pKey->keyp == CK_INVALID_HANDLE)
760 		return (KMF_ERR_BAD_PARAMETER);
761 
762 	(void) memset(&Modulus, 0, sizeof (Modulus));
763 	(void) memset(&Exponent, 0, sizeof (Exponent));
764 	(void) memset(&Prime, 0, sizeof (Prime));
765 	(void) memset(&Subprime, 0, sizeof (Subprime));
766 	(void) memset(&Base, 0, sizeof (Base));
767 	(void) memset(&Value, 0, sizeof (Value));
768 
769 	SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
770 	SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
771 	SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, &Modulus.Length);
772 	SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, Exponent.Data,
773 		&Exponent.Length);
774 
775 	SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
776 	SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
777 	SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, &Prime.Length);
778 	SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, &Subprime.Length);
779 	SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, &Base.Length);
780 	SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, &Value.Length);
781 
782 	switch (pKey->keyalg) {
783 		case KMF_RSA:
784 			/* Get the length of the fields */
785 			rv = C_GetAttributeValue(kmfh->pk11handle,
786 				(CK_OBJECT_HANDLE)pKey->keyp,
787 				rsaTemplate, 4);
788 			if (rv != CKR_OK) {
789 				SET_ERROR(kmfh, rv);
790 				return (KMF_ERR_BAD_PARAMETER);
791 			}
792 
793 			Modulus.Length = rsaTemplate[2].ulValueLen;
794 			Modulus.Data = malloc(Modulus.Length);
795 			if (Modulus.Data == NULL)
796 				return (KMF_ERR_MEMORY);
797 
798 			Exponent.Length = rsaTemplate[3].ulValueLen;
799 			Exponent.Data = malloc(Exponent.Length);
800 			if (Exponent.Data == NULL) {
801 				free(Modulus.Data);
802 				return (KMF_ERR_MEMORY);
803 			}
804 
805 			SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
806 					Modulus.Length);
807 			SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
808 					Exponent.Data, Exponent.Length);
809 			/* Now get the values */
810 			rv = C_GetAttributeValue(kmfh->pk11handle,
811 				(CK_OBJECT_HANDLE)pKey->keyp,
812 				rsaTemplate, 4);
813 			if (rv != CKR_OK) {
814 				SET_ERROR(kmfh, rv);
815 				free(Modulus.Data);
816 				free(Exponent.Data);
817 				return (KMF_ERR_BAD_PARAMETER);
818 			}
819 
820 			/*
821 			 * This is the KEY algorithm, not the
822 			 * signature algorithm.
823 			 */
824 			Algorithm = X509_AlgIdToAlgorithmOid(KMF_ALGID_RSA);
825 			if (Algorithm != NULL) {
826 
827 				/* Encode the RSA Key Data */
828 				if ((asn1 = kmfder_alloc()) == NULL) {
829 					free(Modulus.Data);
830 					free(Exponent.Data);
831 					return (KMF_ERR_MEMORY);
832 				}
833 				if (kmfber_printf(asn1, "{II}",
834 					Modulus.Data, Modulus.Length,
835 					Exponent.Data, Exponent.Length) == -1) {
836 					kmfber_free(asn1, 1);
837 					free(Modulus.Data);
838 					free(Exponent.Data);
839 					return (KMF_ERR_ENCODING);
840 				}
841 				if (kmfber_flatten(asn1, &EncodedKey) == -1) {
842 					kmfber_free(asn1, 1);
843 					free(Modulus.Data);
844 					free(Exponent.Data);
845 					return (KMF_ERR_ENCODING);
846 				}
847 				kmfber_free(asn1, 1);
848 			}
849 
850 			free(Exponent.Data);
851 			free(Modulus.Data);
852 
853 			break;
854 		case KMF_DSA:
855 			/* Get the length of the fields */
856 			rv = C_GetAttributeValue(kmfh->pk11handle,
857 				(CK_OBJECT_HANDLE)pKey->keyp,
858 				dsaTemplate, 6);
859 			if (rv != CKR_OK) {
860 				SET_ERROR(kmfh, rv);
861 				return (KMF_ERR_BAD_PARAMETER);
862 			}
863 			Prime.Length = dsaTemplate[2].ulValueLen;
864 			Prime.Data = malloc(Prime.Length);
865 			if (Prime.Data == NULL) {
866 				return (KMF_ERR_MEMORY);
867 			}
868 
869 			Subprime.Length = dsaTemplate[3].ulValueLen;
870 			Subprime.Data = malloc(Subprime.Length);
871 			if (Subprime.Data == NULL) {
872 				free(Prime.Data);
873 				return (KMF_ERR_MEMORY);
874 			}
875 
876 			Base.Length = dsaTemplate[4].ulValueLen;
877 			Base.Data = malloc(Base.Length);
878 			if (Base.Data == NULL) {
879 				free(Prime.Data);
880 				free(Subprime.Data);
881 				return (KMF_ERR_MEMORY);
882 			}
883 
884 			Value.Length = dsaTemplate[5].ulValueLen;
885 			Value.Data = malloc(Value.Length);
886 			if (Value.Data == NULL) {
887 				free(Prime.Data);
888 				free(Subprime.Data);
889 				free(Base.Data);
890 				return (KMF_ERR_MEMORY);
891 			}
892 			SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
893 					Prime.Length);
894 			SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
895 					Subprime.Length);
896 			SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
897 					Base.Length);
898 			SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
899 					Value.Length);
900 
901 			/* Now get the values */
902 			rv = C_GetAttributeValue(kmfh->pk11handle,
903 				(CK_OBJECT_HANDLE)pKey->keyp,
904 				dsaTemplate, 6);
905 			if (rv != CKR_OK) {
906 				free(Prime.Data);
907 				free(Subprime.Data);
908 				free(Base.Data);
909 				free(Value.Data);
910 				SET_ERROR(kmfh, rv);
911 				return (KMF_ERR_BAD_PARAMETER);
912 			}
913 			/*
914 			 * This is the KEY algorithm, not the
915 			 * signature algorithm.
916 			 */
917 			Algorithm =
918 			    X509_AlgIdToAlgorithmOid(KMF_ALGID_DSA);
919 
920 			/* Encode the DSA Algorithm Parameters */
921 			if ((asn1 = kmfder_alloc()) == NULL) {
922 				free(Prime.Data);
923 				free(Subprime.Data);
924 				free(Base.Data);
925 				free(Value.Data);
926 				return (KMF_ERR_MEMORY);
927 			}
928 
929 			if (kmfber_printf(asn1, "{III}",
930 				Prime.Data, Prime.Length,
931 				Subprime.Data, Subprime.Length,
932 				Base.Data, Base.Length) == -1) {
933 
934 				kmfber_free(asn1, 1);
935 				free(Prime.Data);
936 				free(Subprime.Data);
937 				free(Base.Data);
938 				free(Value.Data);
939 				return (KMF_ERR_ENCODING);
940 			}
941 			if (kmfber_flatten(asn1, &PubKeyParams) == -1) {
942 				kmfber_free(asn1, 1);
943 				free(Prime.Data);
944 				free(Subprime.Data);
945 				free(Base.Data);
946 				free(Value.Data);
947 				return (KMF_ERR_ENCODING);
948 			}
949 			kmfber_free(asn1, 1);
950 			free(Prime.Data);
951 			free(Subprime.Data);
952 			free(Base.Data);
953 
954 			/* Encode the DSA Key Value */
955 			if ((asn1 = kmfder_alloc()) == NULL) {
956 				free(Value.Data);
957 				return (KMF_ERR_MEMORY);
958 			}
959 
960 			if (kmfber_printf(asn1, "I",
961 				Value.Data, Value.Length) == -1) {
962 				kmfber_free(asn1, 1);
963 				free(Value.Data);
964 				return (KMF_ERR_ENCODING);
965 			}
966 			if (kmfber_flatten(asn1, &EncodedKey) == -1) {
967 				kmfber_free(asn1, 1);
968 				free(Value.Data);
969 				return (KMF_ERR_ENCODING);
970 			}
971 			kmfber_free(asn1, 1);
972 			free(Value.Data);
973 			break;
974 		default:
975 			return (KMF_ERR_BAD_PARAMETER);
976 	}
977 
978 	/* Now, build an SPKI structure for the final encoding step */
979 	spki.algorithm.algorithm = *Algorithm;
980 	if (PubKeyParams != NULL) {
981 		spki.algorithm.parameters.Data =
982 			(uchar_t *)PubKeyParams->bv_val;
983 		spki.algorithm.parameters.Length = PubKeyParams->bv_len;
984 	} else {
985 		spki.algorithm.parameters.Data = NULL;
986 		spki.algorithm.parameters.Length = 0;
987 	}
988 
989 	if (EncodedKey != NULL) {
990 		spki.subjectPublicKey.Data = (uchar_t *)EncodedKey->bv_val;
991 		spki.subjectPublicKey.Length = EncodedKey->bv_len;
992 	} else {
993 		spki.subjectPublicKey.Data = NULL;
994 		spki.subjectPublicKey.Length = 0;
995 	}
996 
997 	/* Finally, encode the entire SPKI record */
998 	ret = DerEncodeSPKI(&spki, eData);
999 
1000 cleanup:
1001 	if (EncodedKey) {
1002 		free(EncodedKey->bv_val);
1003 		free(EncodedKey);
1004 	}
1005 
1006 	if (PubKeyParams) {
1007 		free(PubKeyParams->bv_val);
1008 		free(PubKeyParams);
1009 	}
1010 
1011 	return (ret);
1012 }
1013 
1014 
1015 static KMF_RETURN
1016 CreateCertObject(KMF_HANDLE_T handle, char *label, KMF_DATA *pcert)
1017 {
1018 	KMF_RETURN rv = 0;
1019 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1020 
1021 	KMF_X509_CERTIFICATE *signed_cert_ptr = NULL;
1022 	KMF_DATA data;
1023 	KMF_DATA Id;
1024 
1025 	CK_RV ckrv;
1026 	CK_ULONG subject_len, issuer_len, serno_len;
1027 	CK_BYTE *subject, *issuer, *serial, nullserno;
1028 	CK_BBOOL true = TRUE;
1029 	CK_CERTIFICATE_TYPE certtype = CKC_X_509;
1030 	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1031 	CK_ATTRIBUTE x509templ[11];
1032 	CK_OBJECT_HANDLE hCert = NULL;
1033 	int i;
1034 
1035 	if (!kmfh)
1036 		return (KMF_ERR_INTERNAL); /* should not happen */
1037 
1038 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1039 		return (KMF_ERR_INTERNAL); /* should not happen */
1040 
1041 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1042 		return (KMF_ERR_INTERNAL);  /* should not happen */
1043 
1044 	/*
1045 	 * The data *must* be a DER encoded X.509 certificate.
1046 	 * Convert it to a CSSM cert and then parse the fields so
1047 	 * the PKCS#11 attributes can be filled in correctly.
1048 	 */
1049 	rv = DerDecodeSignedCertificate((const KMF_DATA *)pcert,
1050 		&signed_cert_ptr);
1051 	if (rv != KMF_OK) {
1052 		return (KMF_ERR_ENCODING);
1053 	}
1054 
1055 	/*
1056 	 * Encode fields into PKCS#11 attributes.
1057 	 */
1058 
1059 	/* Get the subject name */
1060 	rv = DerEncodeName(&signed_cert_ptr->certificate.subject, &data);
1061 	if (rv == KMF_OK) {
1062 		subject = data.Data;
1063 		subject_len = data.Length;
1064 	} else {
1065 		rv = KMF_ERR_ENCODING;
1066 		goto cleanup;
1067 	}
1068 
1069 	/* Encode the issuer */
1070 	rv = DerEncodeName(&signed_cert_ptr->certificate.issuer, &data);
1071 	if (rv == KMF_OK) {
1072 		issuer = data.Data;
1073 		issuer_len = data.Length;
1074 	} else {
1075 		rv = KMF_ERR_ENCODING;
1076 		goto cleanup;
1077 	}
1078 
1079 	/* Encode serial number */
1080 	if (signed_cert_ptr->certificate.serialNumber.len > 0 &&
1081 	    signed_cert_ptr->certificate.serialNumber.val != NULL) {
1082 		serial = signed_cert_ptr->certificate.serialNumber.val;
1083 		serno_len = signed_cert_ptr->certificate.serialNumber.len;
1084 	} else {
1085 		/*
1086 		 * RFC3280 says to gracefully handle certs with serial numbers
1087 		 * of 0.
1088 		 */
1089 		nullserno = '\0';
1090 		serial  = &nullserno;
1091 		serno_len = 1;
1092 	}
1093 
1094 	/* Generate an ID from the SPKI data */
1095 	rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
1096 			&Id);
1097 
1098 	if (rv != KMF_OK) {
1099 		SET_ERROR(kmfh, rv);
1100 		goto cleanup;
1101 	}
1102 
1103 	i = 0;
1104 	SETATTR(x509templ, i, CKA_CLASS, &certClass,
1105 		sizeof (certClass)); i++;
1106 	SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
1107 		sizeof (certtype)); i++;
1108 	SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
1109 	SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
1110 	SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
1111 	SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
1112 	SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
1113 	SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
1114 	if (label != NULL && strlen(label)) {
1115 		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));
1116 		i++;
1117 	}
1118 	/*
1119 	 * The cert object handle is actually "leaked" here.  If the app
1120 	 * really wants to clean up the data space, it will have to call
1121 	 * KMF_DeleteCert and specify the softtoken keystore.
1122 	 */
1123 	ckrv = C_CreateObject(kmfh->pk11handle, x509templ, i, &hCert);
1124 	if (ckrv != CKR_OK) {
1125 		SET_ERROR(kmfh, rv);
1126 		rv = KMF_ERR_INTERNAL;
1127 	}
1128 	free(subject);
1129 	free(issuer);
1130 
1131 cleanup:
1132 	if (Id.Data != NULL)
1133 		free(Id.Data);
1134 
1135 	if (signed_cert_ptr) {
1136 		KMF_FreeSignedCert(signed_cert_ptr);
1137 		free(signed_cert_ptr);
1138 	}
1139 	return (rv);
1140 }
1141 
1142 
1143 KMF_RETURN
1144 KMFPK11_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
1145 		KMF_DATA *pcert)
1146 {
1147 	KMF_RETURN rv = 0;
1148 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1149 
1150 	if (!kmfh)
1151 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1152 
1153 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1154 		return (KMF_ERR_NO_TOKEN_SELECTED);
1155 
1156 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1157 		return (KMF_ERR_BAD_PARAMETER);
1158 
1159 	rv = CreateCertObject(handle, params->certLabel, pcert);
1160 	return (rv);
1161 }
1162 
1163 
1164 
1165 KMF_RETURN
1166 KMFPK11_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *params)
1167 {
1168 	KMF_RETURN rv = 0;
1169 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1170 	KMF_ENCODE_FORMAT format;
1171 	KMF_DATA  cert1 = { NULL, 0};
1172 	KMF_DATA  cert2 = { NULL, 0};
1173 
1174 	if (!kmfh)
1175 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1176 
1177 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1178 		return (KMF_ERR_NO_TOKEN_SELECTED);
1179 
1180 	if (params == NULL || params->certfile == NULL) {
1181 		return (KMF_ERR_BAD_PARAMETER);
1182 	}
1183 
1184 	/*
1185 	 * Check if the input cert file is a valid certificate and
1186 	 * auto-detect the file format of it.
1187 	 */
1188 	rv = KMF_IsCertFile(handle, params->certfile, &format);
1189 	if (rv != KMF_OK)
1190 		return (rv);
1191 
1192 	/* Read in the CERT file */
1193 	rv = KMF_ReadInputFile(handle, params->certfile, &cert1);
1194 	if (rv != KMF_OK) {
1195 		return (rv);
1196 	}
1197 
1198 	/*
1199 	 * If the input certificate is in PEM format, we need to convert
1200 	 * it to DER first.
1201 	 */
1202 	if (format == KMF_FORMAT_PEM) {
1203 		int derlen;
1204 		rv = KMF_Pem2Der(cert1.Data, cert1.Length,
1205 		    &cert2.Data, &derlen);
1206 		if (rv != KMF_OK) {
1207 			goto out;
1208 		}
1209 		cert2.Length = (size_t)derlen;
1210 	}
1211 
1212 	rv = CreateCertObject(handle, params->certLabel,
1213 	    format == KMF_FORMAT_ASN1 ? &cert1 : &cert2);
1214 
1215 out:
1216 	if (cert1.Data != NULL) {
1217 		free(cert1.Data);
1218 	}
1219 
1220 	if (cert2.Data != NULL) {
1221 		free(cert2.Data);
1222 	}
1223 
1224 	return (rv);
1225 }
1226 
1227 KMF_RETURN
1228 KMFPK11_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
1229 {
1230 	KMF_RETURN rv = 0;
1231 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1232 	OBJLIST *objlist;
1233 	uint32_t numObjects = 0;
1234 
1235 	if (!kmfh)
1236 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1237 
1238 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1239 		return (KMF_ERR_NO_TOKEN_SELECTED);
1240 
1241 	if (params == NULL)
1242 		return (KMF_ERR_BAD_PARAMETER);
1243 
1244 	/*
1245 	 * Use the same search routine as is used for the FindCert
1246 	 * operation.
1247 	 */
1248 	objlist = NULL;
1249 	rv = search_certs(handle,
1250 		params->certLabel, params->issuer,
1251 		params->subject, params->serial,
1252 		params->pkcs11parms.private,
1253 		params->find_cert_validity,
1254 		&objlist, &numObjects);
1255 
1256 	if (rv == KMF_OK && objlist != NULL) {
1257 		OBJLIST *node = objlist;
1258 
1259 		while (node != NULL) {
1260 			CK_RV ckrv;
1261 			ckrv = C_DestroyObject(kmfh->pk11handle,
1262 				node->handle);
1263 			if (ckrv != CKR_OK) {
1264 				SET_ERROR(kmfh, ckrv);
1265 				rv = KMF_ERR_INTERNAL;
1266 				break;
1267 			}
1268 			node = node->next;
1269 		}
1270 		free_objlist(objlist);
1271 	}
1272 
1273 	if (rv == KMF_OK && numObjects == 0)
1274 		rv = KMF_ERR_CERT_NOT_FOUND;
1275 
1276 out:
1277 	return (rv);
1278 }
1279 
1280 KMF_RETURN
1281 KMFPK11_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
1282 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
1283 {
1284 	KMF_RETURN rv = KMF_OK;
1285 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1286 
1287 	CK_RV			ckrv = 0;
1288 	CK_OBJECT_HANDLE	pubKey = CK_INVALID_HANDLE;
1289 	CK_OBJECT_HANDLE	priKey = CK_INVALID_HANDLE;
1290 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1291 
1292 	static CK_OBJECT_CLASS	priClass = CKO_PRIVATE_KEY;
1293 	static CK_OBJECT_CLASS	pubClass = CKO_PUBLIC_KEY;
1294 
1295 	static CK_ULONG	rsaKeyType = CKK_RSA;
1296 	static CK_ULONG	modulusBits = 1024;
1297 	static CK_BYTE	PubExpo[3] = {0x01, 0x00, 0x01};
1298 	static CK_BBOOL	true = TRUE;
1299 	static CK_BBOOL	ontoken = TRUE;
1300 	static CK_BBOOL	false = FALSE;
1301 	static CK_ULONG	dsaKeyType = CKK_DSA;
1302 
1303 	CK_ATTRIBUTE rsaPubKeyTemplate[8];
1304 	CK_ATTRIBUTE rsaPriKeyTemplate[6];
1305 
1306 	static CK_BYTE ckDsaPrime[128] = {
1307 	0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
1308 	0xcf, 0xdd, 0xf9, 0xae, 0x3e, 0x39, 0x7f, 0x9c,
1309 	0xa7, 0x73, 0xc3, 0x00, 0xa3, 0x50, 0x67, 0xc3,
1310 	0xab, 0x49, 0x2c, 0xea, 0x59, 0x10, 0xa4, 0xbc,
1311 	0x09, 0x94, 0xa9, 0x05, 0x3b, 0x0d, 0x35, 0x3c,
1312 	0x55, 0x52, 0x47, 0xf0, 0xe3, 0x72, 0x5b, 0xe8,
1313 	0x72, 0xa0, 0x71, 0x1c, 0x23, 0x4f, 0x6d, 0xe8,
1314 	0xac, 0xe5, 0x21, 0x1b, 0xc0, 0xd8, 0x42, 0xd3,
1315 	0x87, 0xae, 0x83, 0x5e, 0x52, 0x7e, 0x46, 0x09,
1316 	0xb5, 0xc7, 0x3d, 0xd6, 0x00, 0xf5, 0xf2, 0x9c,
1317 	0x84, 0x30, 0x81, 0x7e, 0x7b, 0x30, 0x5b, 0xd5,
1318 	0xab, 0xd0, 0x2f, 0x21, 0xb3, 0xd8, 0xed, 0xdb,
1319 	0x97, 0x77, 0xe4, 0x7e, 0x6c, 0xcc, 0xb9, 0x6b,
1320 	0xdd, 0xaa, 0x96, 0x04, 0xe7, 0xd4, 0x55, 0x11,
1321 	0x53, 0xab, 0xba, 0x95, 0x9a, 0xa2, 0x8c, 0x27,
1322 	0xd9, 0xcf, 0xad, 0xf3, 0xcf, 0x3a, 0x0c, 0x4b};
1323 
1324 	static CK_BYTE ckDsaSubPrime[20] = {
1325 	0xa4, 0x5f, 0x2a, 0x27, 0x09, 0x49, 0xb6, 0xfe,
1326 	0x73, 0xeb, 0x95, 0x7d, 0x00, 0xf3, 0x42, 0xfc,
1327 	0x78, 0x47, 0xb0, 0xd5};
1328 
1329 	static CK_BYTE ckDsaBase[128] = {
1330 	0x5c, 0x57, 0x16, 0x49, 0xef, 0xc8, 0xfb, 0x4b,
1331 	0xee, 0x07, 0x45, 0x3b, 0x6a, 0x1d, 0xf3, 0xe5,
1332 	0xeb, 0xee, 0xad, 0x11, 0x13, 0xe3, 0x52, 0xe3,
1333 	0x0d, 0xc0, 0x21, 0x25, 0xfa, 0xf0, 0x93, 0x1c,
1334 	0x53, 0x4d, 0xdc, 0x0d, 0x76, 0xd2, 0xfe, 0xc2,
1335 	0xd7, 0x72, 0x64, 0x69, 0x53, 0x3d, 0x33, 0xbd,
1336 	0xe1, 0x34, 0xf2, 0x5a, 0x67, 0x83, 0xe0, 0xd3,
1337 	0x1c, 0xd6, 0x41, 0x4d, 0x16, 0xe8, 0x6c, 0x5a,
1338 	0x07, 0x95, 0x21, 0x9a, 0xa3, 0xc4, 0xb9, 0x05,
1339 	0x9d, 0x11, 0xcb, 0xc8, 0xc4, 0x9d, 0x00, 0x1a,
1340 	0xf4, 0x85, 0x2a, 0xa9, 0x20, 0x3c, 0xba, 0x67,
1341 	0xe5, 0xed, 0x31, 0xb2, 0x11, 0xfb, 0x1f, 0x73,
1342 	0xec, 0x61, 0x29, 0xad, 0xc7, 0x68, 0xb2, 0x3f,
1343 	0x38, 0xea, 0xd9, 0x87, 0x83, 0x9e, 0x7e, 0x19,
1344 	0x18, 0xdd, 0xc2, 0xc3, 0x5b, 0x16, 0x6d, 0xce,
1345 	0xcf, 0x88, 0x91, 0x07, 0xe0, 0x2b, 0xa8, 0x54 };
1346 
1347 	static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
1348 	{ CKA_CLASS, &pubClass, sizeof (pubClass) },
1349 	{ CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
1350 	{ CKA_TOKEN, &ontoken, sizeof (ontoken)},
1351 	{ CKA_PRIVATE, &false, sizeof (false)},
1352 	{ CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) },
1353 	{ CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)},
1354 	{ CKA_BASE, &ckDsaBase, sizeof (ckDsaBase) },
1355 	{ CKA_VERIFY, &true, sizeof (true) },
1356 };
1357 
1358 #define	NUMBER_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1359 					sizeof (CK_ATTRIBUTE))
1360 #define	MAX_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1361 				    sizeof (CK_ATTRIBUTE))
1362 
1363 	static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
1364 	{CKA_CLASS, &priClass, sizeof (priClass)},
1365 	{CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
1366 	{CKA_TOKEN, &ontoken, sizeof (ontoken)},
1367 	{CKA_PRIVATE, &true, sizeof (true)},
1368 	{CKA_SIGN, &true, sizeof (true)},
1369 	};
1370 
1371 	CK_ATTRIBUTE labelattr[1];
1372 	CK_ATTRIBUTE idattr[1];
1373 	char IDHashData[SHA1_HASH_LENGTH];
1374 	KMF_DATA IDInput, IDOutput;
1375 
1376 #define	NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1377 					sizeof (CK_ATTRIBUTE))
1378 #define	MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1379 				sizeof (CK_ATTRIBUTE))
1380 
1381 	if (!kmfh)
1382 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1383 
1384 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1385 		return (KMF_ERR_NO_TOKEN_SELECTED);
1386 
1387 	if (params == NULL)
1388 		return (KMF_ERR_BAD_PARAMETER);
1389 
1390 	rv = pk11_authenticate(handle, &params->cred);
1391 	if (rv != KMF_OK) {
1392 		return (rv);
1393 	}
1394 
1395 	if (params->keytype == KMF_RSA) {
1396 		CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN,
1397 			NULL, 0};
1398 		CK_BYTE *modulus;
1399 		CK_ULONG modulusLength;
1400 		CK_ATTRIBUTE modattr[1];
1401 
1402 		SETATTR(rsaPubKeyTemplate, 0, CKA_CLASS,
1403 			&pubClass, sizeof (pubClass));
1404 		SETATTR(rsaPubKeyTemplate, 1, CKA_KEY_TYPE,
1405 			&rsaKeyType, sizeof (rsaKeyType));
1406 		SETATTR(rsaPubKeyTemplate, 2, CKA_TOKEN,
1407 			&false, sizeof (false));
1408 		SETATTR(rsaPubKeyTemplate, 3, CKA_PRIVATE,
1409 			&false, sizeof (false));
1410 		SETATTR(rsaPubKeyTemplate, 4, CKA_MODULUS_BITS,
1411 			&modulusBits, sizeof (modulusBits));
1412 		if (params->rsa_exponent.len > 0 &&
1413 			params->rsa_exponent.val != NULL) {
1414 			SETATTR(rsaPubKeyTemplate, 5,
1415 				CKA_PUBLIC_EXPONENT,
1416 				params->rsa_exponent.val,
1417 				params->rsa_exponent.len);
1418 		} else {
1419 			SETATTR(rsaPubKeyTemplate, 5,
1420 				CKA_PUBLIC_EXPONENT, &PubExpo,
1421 				sizeof (PubExpo));
1422 		}
1423 		SETATTR(rsaPubKeyTemplate, 6, CKA_ENCRYPT,
1424 			&true, sizeof (true));
1425 		SETATTR(rsaPubKeyTemplate, 7, CKA_VERIFY,
1426 			&true, sizeof (true));
1427 
1428 		SETATTR(rsaPriKeyTemplate, 0, CKA_CLASS, &priClass,
1429 			sizeof (priClass));
1430 		SETATTR(rsaPriKeyTemplate, 1, CKA_KEY_TYPE, &rsaKeyType,
1431 			sizeof (rsaKeyType));
1432 		SETATTR(rsaPriKeyTemplate, 2, CKA_TOKEN, &ontoken,
1433 			sizeof (ontoken));
1434 		SETATTR(rsaPriKeyTemplate, 3, CKA_PRIVATE, &true,
1435 			sizeof (true));
1436 		SETATTR(rsaPriKeyTemplate, 4, CKA_DECRYPT, &true,
1437 			sizeof (true));
1438 		SETATTR(rsaPriKeyTemplate, 5, CKA_SIGN, &true,
1439 			sizeof (true));
1440 
1441 		SETATTR(modattr, 0, CKA_MODULUS, NULL, &modulusLength);
1442 
1443 		modulusBits = params->keylength;
1444 
1445 		pubKey = CK_INVALID_HANDLE;
1446 		priKey = CK_INVALID_HANDLE;
1447 		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1448 			rsaPubKeyTemplate,
1449 			(sizeof (rsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1450 			rsaPriKeyTemplate,
1451 			(sizeof (rsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1452 			&pubKey, &priKey);
1453 		if (ckrv != CKR_OK) {
1454 			SET_ERROR(kmfh, ckrv);
1455 			return (KMF_ERR_KEYGEN_FAILED);
1456 		}
1457 
1458 		if (privkey != NULL) {
1459 			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1460 			privkey->keyalg = KMF_RSA;
1461 			privkey->keyclass = KMF_ASYM_PRI;
1462 			privkey->keyp = (void *)priKey;
1463 		}
1464 		if (pubkey != NULL) {
1465 			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1466 			pubkey->keyalg = KMF_RSA;
1467 			pubkey->keyclass = KMF_ASYM_PUB;
1468 			pubkey->keyp = (void *)pubKey;
1469 		}
1470 
1471 		/* Get the Modulus field to use as input for creating the ID */
1472 		rv = C_GetAttributeValue(kmfh->pk11handle,
1473 			(CK_OBJECT_HANDLE)pubKey,
1474 			modattr, 1);
1475 		if (rv != CKR_OK) {
1476 			SET_ERROR(kmfh, ckrv);
1477 			return (KMF_ERR_BAD_PARAMETER);
1478 		}
1479 
1480 		modulusLength = modattr[0].ulValueLen;
1481 		modulus = malloc(modulusLength);
1482 		if (modulus == NULL)
1483 			return (KMF_ERR_MEMORY);
1484 
1485 		modattr[0].pValue = modulus;
1486 		rv = C_GetAttributeValue(kmfh->pk11handle,
1487 			(CK_OBJECT_HANDLE)pubKey,
1488 			modattr, 1);
1489 		if (rv != CKR_OK) {
1490 			SET_ERROR(kmfh, ckrv);
1491 			free(modulus);
1492 			return (KMF_ERR_BAD_PARAMETER);
1493 		}
1494 
1495 		IDInput.Data = modulus;
1496 		IDInput.Length = modulusLength;
1497 
1498 	} else if (params->keytype == KMF_DSA) {
1499 		CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
1500 		CK_BYTE *keyvalue;
1501 		CK_ULONG valueLen;
1502 		CK_ATTRIBUTE valattr[1];
1503 
1504 		SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
1505 				&ontoken, sizeof (ontoken));
1506 		SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen);
1507 
1508 		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1509 			ckDsaPubKeyTemplate,
1510 			(sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1511 			ckDsaPriKeyTemplate,
1512 			(sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1513 			&pubKey, &priKey);
1514 		if (ckrv != CKR_OK) {
1515 			SET_ERROR(kmfh, ckrv);
1516 			return (KMF_ERR_KEYGEN_FAILED);
1517 		}
1518 
1519 		if (privkey != NULL) {
1520 			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1521 			privkey->keyalg = KMF_DSA;
1522 			privkey->keyclass = KMF_ASYM_PRI;
1523 			privkey->keyp = (void *)priKey;
1524 		}
1525 		if (pubkey != NULL) {
1526 			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1527 			pubkey->keyalg = KMF_DSA;
1528 			pubkey->keyclass = KMF_ASYM_PUB;
1529 			pubkey->keyp = (void *)pubKey;
1530 		}
1531 		/* Get the Public Value to use as input for creating the ID */
1532 		rv = C_GetAttributeValue(hSession,
1533 			(CK_OBJECT_HANDLE)pubKey,
1534 			valattr, 1);
1535 		if (rv != CKR_OK) {
1536 			SET_ERROR(kmfh, ckrv);
1537 			return (KMF_ERR_BAD_PARAMETER);
1538 		}
1539 
1540 		valueLen = valattr[0].ulValueLen;
1541 		keyvalue = malloc(valueLen);
1542 		if (keyvalue == NULL)
1543 			return (KMF_ERR_MEMORY);
1544 
1545 		valattr[0].pValue = keyvalue;
1546 		rv = C_GetAttributeValue(hSession,
1547 			(CK_OBJECT_HANDLE)pubKey,
1548 			valattr, 1);
1549 		if (rv != CKR_OK) {
1550 			SET_ERROR(kmfh, ckrv);
1551 			free(keyvalue);
1552 			return (KMF_ERR_BAD_PARAMETER);
1553 		}
1554 
1555 		IDInput.Data = keyvalue;
1556 		IDInput.Length = valueLen;
1557 	} else {
1558 		return (KMF_ERR_BAD_PARAMETER);
1559 	}
1560 
1561 	if (params->keylabel != NULL &&
1562 		strlen(params->keylabel)) {
1563 
1564 		SETATTR(labelattr, 0, CKA_LABEL, params->keylabel,
1565 			strlen(params->keylabel));
1566 
1567 		/* Set the CKA_LABEL if one was indicated */
1568 		if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1569 			labelattr, 1)) != CKR_OK) {
1570 			SET_ERROR(kmfh, ckrv);
1571 			rv = KMF_ERR_INTERNAL;
1572 			goto cleanup;
1573 		}
1574 		if (pubkey != NULL) {
1575 			pubkey->keylabel =
1576 				(char *)strdup(params->keylabel);
1577 			if (pubkey->keylabel == NULL) {
1578 				rv = KMF_ERR_MEMORY;
1579 				goto cleanup;
1580 			}
1581 		}
1582 		if ((ckrv = C_SetAttributeValue(hSession, priKey,
1583 			labelattr, 1)) != CKR_OK) {
1584 			SET_ERROR(kmfh, ckrv);
1585 			rv = KMF_ERR_INTERNAL;
1586 			goto cleanup;
1587 		}
1588 		if (privkey != NULL) {
1589 			privkey->keylabel =
1590 				(char *)strdup(params->keylabel);
1591 			if (privkey->keylabel == NULL) {
1592 				rv = KMF_ERR_MEMORY;
1593 				goto cleanup;
1594 			}
1595 		}
1596 	}
1597 
1598 	/* Now, assign a CKA_ID value so it can be searched */
1599 	/* ID_Input was assigned above in the RSA or DSA keygen section */
1600 	IDOutput.Data = (uchar_t *)IDHashData;
1601 	IDOutput.Length = sizeof (IDHashData);
1602 
1603 	rv = DigestData(hSession, &IDInput, &IDOutput);
1604 	free(IDInput.Data);
1605 
1606 	if (rv != CKR_OK) {
1607 		SET_ERROR(kmfh, rv);
1608 		goto cleanup;
1609 	}
1610 	SETATTR(idattr, 0, CKA_ID, IDOutput.Data, IDOutput.Length);
1611 	if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1612 			idattr, 1)) != CKR_OK) {
1613 		SET_ERROR(kmfh, ckrv);
1614 		rv = KMF_ERR_INTERNAL;
1615 		goto cleanup;
1616 	}
1617 	if ((ckrv = C_SetAttributeValue(hSession, priKey,
1618 			idattr, 1)) != CKR_OK) {
1619 		SET_ERROR(kmfh, ckrv);
1620 		rv = KMF_ERR_INTERNAL;
1621 		goto cleanup;
1622 	}
1623 
1624 cleanup:
1625 	if (rv != KMF_OK) {
1626 		if (pubKey != CK_INVALID_HANDLE)
1627 			(void) C_DestroyObject(hSession, pubKey);
1628 		if (priKey != CK_INVALID_HANDLE)
1629 			(void) C_DestroyObject(hSession, priKey);
1630 		if (privkey) {
1631 			privkey->keyp = NULL;
1632 			if (privkey->keylabel)
1633 				free(privkey->keylabel);
1634 		}
1635 		if (pubkey) {
1636 			pubkey->keyp = NULL;
1637 			if (pubkey->keylabel)
1638 				free(pubkey->keylabel);
1639 		}
1640 	}
1641 	return (rv);
1642 }
1643 
1644 KMF_RETURN
1645 KMFPK11_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1646 	KMF_KEY_HANDLE *key, boolean_t destroy)
1647 {
1648 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1649 	CK_RV ckrv = CKR_OK;
1650 	KMF_RETURN rv = KMF_OK;
1651 
1652 	if (!kmfh)
1653 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1654 
1655 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1656 		return (KMF_ERR_NO_TOKEN_SELECTED);
1657 
1658 	if (key == NULL || key->keyp == NULL)
1659 		return (KMF_ERR_BAD_PARAMETER);
1660 
1661 	if (key->keyclass != KMF_ASYM_PUB &&
1662 		key->keyclass != KMF_ASYM_PRI &&
1663 		key->keyclass != KMF_SYMMETRIC)
1664 		return (KMF_ERR_BAD_KEY_CLASS);
1665 
1666 	if (destroy) {
1667 		rv = pk11_authenticate(handle, &params->cred);
1668 		if (rv != KMF_OK) {
1669 			return (rv);
1670 		}
1671 	}
1672 
1673 	if (!key->israw && destroy)
1674 		ckrv = C_DestroyObject(kmfh->pk11handle,
1675 			(CK_OBJECT_HANDLE)key->keyp);
1676 
1677 	if (ckrv != CKR_OK) {
1678 		SET_ERROR(kmfh, ckrv);
1679 		/* Report authentication failures to the caller */
1680 		if (ckrv == CKR_PIN_EXPIRED ||
1681 		    ckrv == CKR_SESSION_READ_ONLY)
1682 			rv = KMF_ERR_AUTH_FAILED;
1683 		else
1684 			rv = KMF_ERR_INTERNAL;
1685 	}
1686 	return (rv);
1687 
1688 }
1689 
1690 KMF_RETURN
1691 KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1692 	KMF_OID *algOID,
1693 	KMF_DATA *tobesigned,
1694 	KMF_DATA *output)
1695 {
1696 	CK_RV			ckrv;
1697 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1698 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1699 	CK_MECHANISM		mechanism;
1700 	PKCS_ALGORITHM_MAP 	*pAlgMap;
1701 	KMF_ALGORITHM_INDEX		AlgId;
1702 
1703 	if (!kmfh)
1704 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1705 
1706 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1707 		return (KMF_ERR_NO_TOKEN_SELECTED);
1708 
1709 	if (keyp == NULL || algOID == NULL ||
1710 	    tobesigned == NULL || output == NULL)
1711 		return (KMF_ERR_BAD_PARAMETER);
1712 
1713 	/* These functions are available to the plugin from libkmf */
1714 	AlgId = X509_AlgorithmOidToAlgId(algOID);
1715 	if (AlgId == KMF_ALGID_NONE)
1716 		return (KMF_ERR_BAD_PARAMETER);
1717 
1718 	/* Map the Algorithm OID to a PKCS#11 mechanism */
1719 	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1720 		AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1721 
1722 	if (pAlgMap == NULL)
1723 		return (KMF_ERR_BAD_PARAMETER);
1724 
1725 	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1726 	mechanism.pParameter = NULL;
1727 	mechanism.ulParameterLen = 0;
1728 
1729 	ckrv = C_SignInit(hSession, &mechanism, (CK_OBJECT_HANDLE)keyp->keyp);
1730 	if (ckrv != CKR_OK) {
1731 		SET_ERROR(kmfh, ckrv);
1732 		return (KMF_ERR_INTERNAL);
1733 	}
1734 
1735 	ckrv = C_Sign(hSession,
1736 		tobesigned->Data, tobesigned->Length,
1737 		output->Data, (CK_ULONG *)&output->Length);
1738 
1739 	if (ckrv != CKR_OK) {
1740 		SET_ERROR(kmfh, ckrv);
1741 		return (KMF_ERR_INTERNAL);
1742 	}
1743 
1744 	return (KMF_OK);
1745 }
1746 
1747 KMF_RETURN
1748 KMFPK11_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1749 {
1750 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1751 
1752 	*msgstr = NULL;
1753 	if (kmfh->lasterr.errcode != 0) {
1754 		char *e = pkcs11_strerror(kmfh->lasterr.errcode);
1755 		if (e == NULL || (*msgstr = (char *)strdup(e)) == NULL) {
1756 			return (KMF_ERR_MEMORY);
1757 		}
1758 	}
1759 
1760 	return (KMF_OK);
1761 }
1762 
1763 static CK_RV
1764 getObjectKeytype(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1765 	CK_ULONG *keytype)
1766 {
1767 	CK_RV rv = CKR_OK;
1768 	CK_ATTRIBUTE templ;
1769 	CK_ULONG len = sizeof (CK_ULONG);
1770 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1771 
1772 	templ.type = CKA_KEY_TYPE;
1773 	templ.pValue = keytype;
1774 	templ.ulValueLen = len;
1775 
1776 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1777 
1778 	return (rv);
1779 
1780 }
1781 static CK_RV
1782 getObjectLabel(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1783 	char **outlabel)
1784 {
1785 	CK_RV rv = CKR_OK;
1786 	CK_ATTRIBUTE templ;
1787 	char	Label[BUFSIZ];
1788 	CK_ULONG len = sizeof (Label);
1789 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1790 
1791 	(void) memset(Label, 0, len);
1792 	templ.type = CKA_LABEL;
1793 	templ.pValue = Label;
1794 	templ.ulValueLen = len;
1795 
1796 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1797 	if (rv == CKR_OK) {
1798 		*outlabel = (char *)strdup(Label);
1799 	} else {
1800 		*outlabel = NULL;
1801 	}
1802 	return (rv);
1803 }
1804 
1805 KMF_RETURN
1806 KMFPK11_GetPrikeyByCert(KMF_HANDLE_T handle,
1807 	KMF_CRYPTOWITHCERT_PARAMS *params,
1808 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
1809 	KMF_KEY_ALG keytype)
1810 {
1811 	KMF_X509_SPKI *pubkey;
1812 	KMF_X509_CERTIFICATE *SignerCert = NULL;
1813 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1814 	KMF_RETURN rv = KMF_OK;
1815 	CK_RV ckrv = CKR_OK;
1816 	CK_ATTRIBUTE templ[4];
1817 	CK_OBJECT_HANDLE pri_obj = CK_INVALID_HANDLE;
1818 	CK_ULONG obj_count;
1819 	CK_OBJECT_CLASS certClass = CKO_PRIVATE_KEY;
1820 	CK_BBOOL true = TRUE;
1821 	KMF_DATA Id = { NULL, 0 };
1822 
1823 	/* Decode the signer cert so we can get the SPKI data */
1824 	if ((rv = DerDecodeSignedCertificate(SignerCertData,
1825 	    &SignerCert)) != KMF_OK)
1826 		return (rv);
1827 
1828 	/* Get the public key info from the signer certificate */
1829 	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
1830 
1831 	/* Generate an ID from the SPKI data */
1832 	rv = GetIDFromSPKI(pubkey, &Id);
1833 
1834 	if (rv != KMF_OK) {
1835 		SET_ERROR(kmfh, rv);
1836 		goto errout;
1837 	}
1838 
1839 	SETATTR(templ, 0, CKA_CLASS, &certClass, sizeof (certClass));
1840 	SETATTR(templ, 1, CKA_TOKEN, &true, sizeof (true));
1841 	SETATTR(templ, 2, CKA_PRIVATE, &true, sizeof (true));
1842 	SETATTR(templ, 3, CKA_ID, Id.Data, Id.Length);
1843 
1844 	rv = pk11_authenticate(handle, &params->cred);
1845 	if (rv != KMF_OK) {
1846 		return (rv);
1847 	}
1848 
1849 	if ((ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, 4)) != CKR_OK) {
1850 		SET_ERROR(kmfh, ckrv);
1851 		rv = KMF_ERR_INTERNAL;
1852 		goto errout;
1853 	}
1854 
1855 	if ((rv = C_FindObjects(kmfh->pk11handle, &pri_obj, 1,
1856 	    &obj_count)) != CKR_OK) {
1857 		SET_ERROR(kmfh, ckrv);
1858 		rv = KMF_ERR_INTERNAL;
1859 		goto errout;
1860 	}
1861 
1862 	if (obj_count == 0) {
1863 		SET_ERROR(kmfh, ckrv);
1864 		rv = KMF_ERR_INTERNAL;
1865 		goto errout;
1866 	}
1867 
1868 	key->kstype = KMF_KEYSTORE_PK11TOKEN;
1869 	key->keyclass = KMF_ASYM_PRI;
1870 	key->keyalg = keytype;
1871 	key->keyp = (void *)pri_obj;
1872 
1873 	(void) C_FindObjectsFinal(kmfh->pk11handle);
1874 
1875 	ckrv = getObjectLabel(handle, (CK_OBJECT_HANDLE)key->keyp,
1876 		&key->keylabel);
1877 
1878 	if (ckrv != CKR_OK) {
1879 		SET_ERROR(handle, ckrv);
1880 		rv = KMF_ERR_INTERNAL;
1881 	} else {
1882 		rv = KMF_OK;
1883 	}
1884 
1885 	if (rv == KMF_OK && params->format == KMF_FORMAT_RAWKEY) {
1886 		KMF_RAW_KEY_DATA *rkey = NULL;
1887 		rv = keyObj2RawKey(handle, key, &rkey);
1888 		if (rv == KMF_OK) {
1889 			key->keyp = rkey;
1890 			key->israw = TRUE;
1891 		}
1892 	}
1893 
1894 errout:
1895 	if (Id.Data != NULL)
1896 		free(Id.Data);
1897 
1898 	if (SignerCert != NULL) {
1899 		KMF_FreeSignedCert(SignerCert);
1900 		free(SignerCert);
1901 	}
1902 	return (rv);
1903 }
1904 
1905 KMF_RETURN
1906 KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1907 	KMF_OID *algOID, KMF_DATA *ciphertext,
1908 	KMF_DATA *output)
1909 {
1910 	CK_RV			ckrv;
1911 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1912 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1913 	CK_MECHANISM		mechanism;
1914 	PKCS_ALGORITHM_MAP 	*pAlgMap;
1915 	KMF_ALGORITHM_INDEX	AlgId;
1916 	CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
1917 	uint8_t *in_data, *out_data;
1918 	int i, blocks;
1919 	CK_ATTRIBUTE ckTemplate[1];
1920 
1921 	if (!kmfh)
1922 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1923 
1924 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1925 		return (KMF_ERR_NO_TOKEN_SELECTED);
1926 
1927 	if (key == NULL || algOID == NULL ||
1928 	    ciphertext == NULL || output == NULL)
1929 		return (KMF_ERR_BAD_PARAMETER);
1930 
1931 	AlgId = X509_AlgorithmOidToAlgId(algOID);
1932 	if (AlgId == KMF_ALGID_NONE)
1933 		return (KMF_ERR_BAD_PARAMETER);
1934 
1935 	/* Map the Algorithm ID to a PKCS#11 mechanism */
1936 	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1937 	    AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1938 
1939 	if (pAlgMap == NULL)
1940 		return (KMF_ERR_BAD_PARAMETER);
1941 
1942 	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1943 	mechanism.pParameter = NULL;
1944 	mechanism.ulParameterLen = 0;
1945 
1946 	SETATTR(ckTemplate, 0, CKA_MODULUS, (CK_BYTE *)NULL,
1947 	    sizeof (CK_ULONG));
1948 
1949 	/* Get the modulus length */
1950 	ckrv = C_GetAttributeValue(hSession,
1951 	    (CK_OBJECT_HANDLE)key->keyp, ckTemplate, 1);
1952 
1953 	if (ckrv != CKR_OK)  {
1954 		SET_ERROR(kmfh, ckrv);
1955 		return (KMF_ERR_INTERNAL);
1956 	}
1957 
1958 	block_len = ckTemplate[0].ulValueLen;
1959 
1960 	/* Compute the number of times to do single-part decryption */
1961 	blocks = ciphertext->Length/block_len;
1962 
1963 	out_data = output->Data;
1964 	in_data = ciphertext->Data;
1965 	out_len = block_len - 11;
1966 
1967 	for (i = 0; i < blocks; i++) {
1968 		ckrv = C_DecryptInit(hSession, &mechanism,
1969 			(CK_OBJECT_HANDLE)key->keyp);
1970 
1971 		if (ckrv != CKR_OK) {
1972 			SET_ERROR(kmfh, ckrv);
1973 			return (KMF_ERR_INTERNAL);
1974 		}
1975 
1976 		ckrv = C_Decrypt(hSession, in_data, block_len,
1977 		    out_data, (CK_ULONG *)&out_len);
1978 
1979 		if (ckrv != CKR_OK) {
1980 			SET_ERROR(kmfh, ckrv);
1981 			return (KMF_ERR_INTERNAL);
1982 		}
1983 
1984 		out_data += out_len;
1985 		total_decrypted += out_len;
1986 		in_data += block_len;
1987 
1988 	}
1989 
1990 	output->Length = total_decrypted;
1991 	return (KMF_OK);
1992 }
1993 
1994 static void
1995 attr2bigint(CK_ATTRIBUTE_PTR attr, KMF_BIGINT *big)
1996 {
1997 	big->val = attr->pValue;
1998 	big->len = attr->ulValueLen;
1999 }
2000 
2001 
2002 static KMF_RETURN
2003 get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2004 {
2005 	KMF_RETURN rv = KMF_OK;
2006 	CK_RV ckrv;
2007 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2008 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
2009 		{ CKA_MODULUS, NULL, 0 },
2010 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
2011 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
2012 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
2013 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
2014 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
2015 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
2016 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
2017 	    };
2018 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2019 	int		i;
2020 
2021 	if ((ckrv = C_GetAttributeValue(sess, obj,
2022 			rsa_pri_attrs, count)) != CKR_OK) {
2023 		SET_ERROR(kmfh, ckrv);
2024 		/* Tell the caller know why the key data cannot be retrieved. */
2025 		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2026 			return (KMF_ERR_SENSITIVE_KEY);
2027 		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2028 			return (KMF_ERR_UNEXTRACTABLE_KEY);
2029 		else
2030 			return (KMF_ERR_INTERNAL);
2031 	}
2032 
2033 	/* Allocate memory for each attribute. */
2034 	for (i = 0; i < count; i++) {
2035 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2036 		    rsa_pri_attrs[i].ulValueLen == 0) {
2037 			rsa_pri_attrs[i].ulValueLen = 0;
2038 			continue;
2039 		}
2040 		if ((rsa_pri_attrs[i].pValue =
2041 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2042 			rv = KMF_ERR_MEMORY;
2043 			goto end;
2044 		}
2045 	}
2046 	/* Now that we have space, really get the attributes */
2047 	if ((rv = C_GetAttributeValue(sess, obj,
2048 			rsa_pri_attrs, count)) != CKR_OK) {
2049 		SET_ERROR(kmfh, rv);
2050 		rv = KMF_ERR_INTERNAL;
2051 		goto end;
2052 	}
2053 	i = 0;
2054 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2055 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2056 
2057 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2058 	    rsa_pri_attrs[i].ulValueLen != 0)
2059 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->priexp);
2060 	i++;
2061 
2062 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2063 	    rsa_pri_attrs[i].ulValueLen != 0)
2064 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime1);
2065 	i++;
2066 
2067 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2068 	    rsa_pri_attrs[i].ulValueLen != 0)
2069 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime2);
2070 	i++;
2071 
2072 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2073 	    rsa_pri_attrs[i].ulValueLen != 0)
2074 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp1);
2075 	i++;
2076 
2077 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2078 	    rsa_pri_attrs[i].ulValueLen != 0)
2079 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp2);
2080 	i++;
2081 
2082 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2083 	    rsa_pri_attrs[i].ulValueLen != 0)
2084 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->coef);
2085 	i++;
2086 
2087 end:
2088 	if (rv != KMF_OK) {
2089 		for (i = 0; i < count; i++) {
2090 			if (rsa_pri_attrs[i].pValue != NULL)
2091 				free(rsa_pri_attrs[i].pValue);
2092 		}
2093 		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2094 	}
2095 	return (rv);
2096 }
2097 
2098 static KMF_RETURN
2099 get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2100 {
2101 	KMF_RETURN rv = KMF_OK;
2102 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2103 	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2104 		{ CKA_PRIME, NULL, 0 },
2105 		{ CKA_SUBPRIME, NULL, 0 },
2106 		{ CKA_BASE, NULL, 0 },
2107 		{ CKA_VALUE, NULL, 0 }
2108 	};
2109 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2110 	int		i;
2111 
2112 	if ((rv = C_GetAttributeValue(sess, obj,
2113 		dsa_pri_attrs, count)) != CKR_OK) {
2114 		SET_ERROR(kmfh, rv);
2115 		return (KMF_ERR_INTERNAL);
2116 	}
2117 
2118 	/* Allocate memory for each attribute. */
2119 	for (i = 0; i < count; i++) {
2120 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2121 		    dsa_pri_attrs[i].ulValueLen == 0) {
2122 			dsa_pri_attrs[i].ulValueLen = 0;
2123 			continue;
2124 		}
2125 		if ((dsa_pri_attrs[i].pValue =
2126 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2127 			rv = KMF_ERR_MEMORY;
2128 			goto end;
2129 		}
2130 	}
2131 	if ((rv = C_GetAttributeValue(sess, obj,
2132 		dsa_pri_attrs, count)) != CKR_OK) {
2133 		SET_ERROR(kmfh, rv);
2134 		rv = KMF_ERR_INTERNAL;
2135 		goto end;
2136 	}
2137 
2138 	/* Fill in all the temp variables.  They are all required. */
2139 	i = 0;
2140 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2141 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2142 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2143 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2144 
2145 end:
2146 	if (rv != KMF_OK) {
2147 		for (i = 0; i < count; i++) {
2148 			if (dsa_pri_attrs[i].pValue != NULL)
2149 				free(dsa_pri_attrs[i].pValue);
2150 		}
2151 		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2152 	}
2153 	return (rv);
2154 }
2155 
2156 static KMF_RETURN
2157 get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2158 {
2159 	KMF_RETURN rv = KMF_OK;
2160 	CK_RV	ckrv;
2161 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2162 	CK_ATTRIBUTE	sym_attr[1];
2163 	CK_ULONG	value_len = 0;
2164 
2165 	/* find the key length first */
2166 	sym_attr[0].type = CKA_VALUE;
2167 	sym_attr[0].pValue = NULL;
2168 	sym_attr[0].ulValueLen = value_len;
2169 	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2170 		/*
2171 		 * Don't return error if the key is sensitive, just
2172 		 * don't return any raw data.  Operations like "list"
2173 		 * need to succeed even if the raw data is not
2174 		 * available.
2175 		 */
2176 		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2177 			rawsym->keydata.val = NULL;
2178 			rawsym->keydata.len = 0;
2179 			return (CKR_OK);
2180 		}
2181 		SET_ERROR(kmfh, ckrv);
2182 		return (KMF_ERR_INTERNAL);
2183 	}
2184 
2185 	/* Allocate memory for pValue */
2186 	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2187 	if (sym_attr[0].pValue == NULL) {
2188 		return (KMF_ERR_MEMORY);
2189 	}
2190 
2191 	/* get the key data */
2192 	if ((rv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2193 		SET_ERROR(kmfh, rv);
2194 		free(sym_attr[0].pValue);
2195 		return (KMF_ERR_INTERNAL);
2196 	}
2197 
2198 	rawsym->keydata.val = sym_attr[0].pValue;
2199 	rawsym->keydata.len = sym_attr[0].ulValueLen;
2200 	return (rv);
2201 }
2202 
2203 static KMF_RETURN
2204 keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2205 	KMF_RAW_KEY_DATA **outkey)
2206 {
2207 	KMF_RETURN rv = KMF_OK;
2208 	KMF_RAW_KEY_DATA *rkey;
2209 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2210 
2211 	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2212 	if (rkey == NULL)
2213 		return (KMF_ERR_MEMORY);
2214 
2215 	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2216 
2217 	rkey->keytype = inkey->keyalg;
2218 
2219 	if (inkey->keyalg == KMF_RSA) {
2220 		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2221 			&rkey->rawdata.rsa);
2222 	} else if (inkey->keyalg == KMF_DSA) {
2223 		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2224 			&rkey->rawdata.dsa);
2225 	} else if (inkey->keyalg == KMF_AES ||
2226 	    inkey->keyalg == KMF_RC4 ||
2227 	    inkey->keyalg == KMF_DES ||
2228 	    inkey->keyalg == KMF_DES3) {
2229 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2230 		    &rkey->rawdata.sym);
2231 	} else {
2232 		rv = KMF_ERR_BAD_PARAMETER;
2233 	}
2234 
2235 	if (rv == KMF_OK) {
2236 		*outkey = rkey;
2237 	} else if (rkey != NULL) {
2238 		free(rkey);
2239 		*outkey = NULL;
2240 	}
2241 
2242 	return (rv);
2243 }
2244 
2245 
2246 static KMF_RETURN
2247 kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2248 {
2249 	switch (keyalg) {
2250 	case KMF_RSA:
2251 		*type = CKK_RSA;
2252 		break;
2253 	case KMF_DSA:
2254 		*type = CKK_DSA;
2255 		break;
2256 	case KMF_AES:
2257 		*type = CKK_AES;
2258 		break;
2259 	case KMF_RC4:
2260 		*type = CKK_RC4;
2261 		break;
2262 	case KMF_DES:
2263 		*type = CKK_DES;
2264 		break;
2265 	case KMF_DES3:
2266 		*type = CKK_DES3;
2267 		break;
2268 	default:
2269 		return (KMF_ERR_BAD_KEY_TYPE);
2270 	}
2271 
2272 	return (KMF_OK);
2273 }
2274 
2275 static int
2276 IDStringToData(char *idstr, KMF_DATA *iddata)
2277 {
2278 	int len, i;
2279 	char *iddup, *byte;
2280 	uint_t lvalue;
2281 
2282 	if (idstr == NULL || !strlen(idstr))
2283 		return (-1);
2284 
2285 	iddup = (char *)strdup(idstr);
2286 	if (iddup == NULL)
2287 		return (KMF_ERR_MEMORY);
2288 
2289 	len = strlen(iddup) / 3  + 1;
2290 	iddata->Data = malloc(len);
2291 	if (iddata->Data == NULL)
2292 		return (KMF_ERR_MEMORY);
2293 	(void) memset(iddata->Data, 0, len);
2294 	iddata->Length = len;
2295 
2296 	byte = strtok(iddup, ":");
2297 	if (byte == NULL) {
2298 		free(iddup);
2299 		free(iddata->Data);
2300 		iddata->Data = NULL;
2301 		iddata->Length = 0;
2302 		return (-1);
2303 	}
2304 
2305 	i = 0;
2306 	do {
2307 		(void) sscanf(byte, "%x", &lvalue);
2308 		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2309 		byte = strtok(NULL, ":");
2310 	} while (byte != NULL && i < len);
2311 
2312 	iddata->Length = i;
2313 	free(iddup);
2314 	return (0);
2315 }
2316 
2317 KMF_RETURN
2318 KMFPK11_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
2319 	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
2320 {
2321 	KMF_RETURN rv = KMF_OK;
2322 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2323 	uint32_t want_keys, i;
2324 	CK_RV ckrv;
2325 	CK_ATTRIBUTE pTmpl[10];
2326 	CK_OBJECT_CLASS class;
2327 	CK_BBOOL true = TRUE;
2328 	CK_ULONG alg;
2329 	CK_BBOOL is_token;
2330 
2331 	if (!kmfh)
2332 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2333 
2334 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2335 		return (KMF_ERR_NO_TOKEN_SELECTED);
2336 
2337 	if (parms == NULL || numkeys == NULL)
2338 		return (KMF_ERR_BAD_PARAMETER);
2339 
2340 	if (numkeys != NULL && *numkeys > 0)
2341 		want_keys = *numkeys;
2342 	else
2343 		want_keys = MAXINT; /* count them all */
2344 
2345 	is_token = parms->pkcs11parms.token;
2346 	if (parms->keyclass == KMF_ASYM_PUB) {
2347 		class = CKO_PUBLIC_KEY;
2348 	} else if (parms->keyclass == KMF_ASYM_PRI) {
2349 		class = CKO_PRIVATE_KEY;
2350 	} else if (parms->keyclass == KMF_SYMMETRIC) {
2351 		class = CKO_SECRET_KEY;
2352 	} else {
2353 		return (KMF_ERR_BAD_KEY_CLASS);
2354 	}
2355 
2356 	i = 0;
2357 	pTmpl[i].type = CKA_TOKEN;
2358 	pTmpl[i].pValue = &is_token;
2359 	pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
2360 	i++;
2361 
2362 	pTmpl[i].type = CKA_CLASS;
2363 	pTmpl[i].pValue = &class;
2364 	pTmpl[i].ulValueLen = sizeof (class);
2365 	i++;
2366 
2367 	if (parms->findLabel != NULL && strlen(parms->findLabel)) {
2368 		pTmpl[i].type = CKA_LABEL;
2369 		pTmpl[i].pValue = parms->findLabel;
2370 		pTmpl[i].ulValueLen = strlen(parms->findLabel);
2371 		i++;
2372 	}
2373 
2374 	if (parms->keytype != 0) {
2375 		rv = kmf2pk11keytype(parms->keytype, &alg);
2376 		if (rv != KMF_OK) {
2377 			return (KMF_ERR_BAD_KEY_TYPE);
2378 		}
2379 		pTmpl[i].type = CKA_KEY_TYPE;
2380 		pTmpl[i].pValue = &alg;
2381 		pTmpl[i].ulValueLen = sizeof (alg);
2382 		i++;
2383 	}
2384 
2385 	if (parms->idstr != NULL) {
2386 		KMF_DATA iddata = { NULL, 0 };
2387 
2388 		/*
2389 		 * ID String parameter is assumed to be of form:
2390 		 * XX:XX:XX:XX:XX ... :XX
2391 		 * where XX is a hex number.
2392 		 *
2393 		 * We must convert this back to binary in order to
2394 		 * use it in a search.
2395 		 */
2396 		rv = IDStringToData(parms->idstr, &iddata);
2397 		if (rv == KMF_OK) {
2398 			pTmpl[i].type = CKA_ID;
2399 			pTmpl[i].pValue = iddata.Data;
2400 			pTmpl[i].ulValueLen = iddata.Length;
2401 			i++;
2402 		} else {
2403 			return (rv);
2404 		}
2405 	}
2406 
2407 	if (parms->pkcs11parms.private) {
2408 		pTmpl[i].type = CKA_PRIVATE;
2409 		pTmpl[i].pValue = &true;
2410 		pTmpl[i].ulValueLen = sizeof (true);
2411 		i++;
2412 	}
2413 
2414 	/*
2415 	 * Authenticate if the object is a token object,
2416 	 * a private or secred key, or if the user passed in credentials.
2417 	 */
2418 	if (parms->cred.credlen > 0) {
2419 		rv = pk11_authenticate(handle, &parms->cred);
2420 		if (rv != KMF_OK) {
2421 			return (rv);
2422 		}
2423 	}
2424 
2425 	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2426 	if (ckrv == CKR_OK) {
2427 		CK_ULONG obj_count, n = 0;
2428 		while (ckrv == CKR_OK && n < want_keys) {
2429 			CK_OBJECT_HANDLE hObj;
2430 
2431 			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2432 				1, &obj_count);
2433 			if (ckrv == CKR_OK && obj_count == 1) {
2434 				if (keys != NULL) {
2435 					CK_ULONG keytype;
2436 					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2437 					keys[n].keyclass = parms->keyclass;
2438 					keys[n].israw = FALSE;
2439 					keys[n].keyp = (void *)hObj;
2440 
2441 					ckrv = getObjectKeytype(handle,
2442 						(CK_OBJECT_HANDLE)keys[n].keyp,
2443 						&keytype);
2444 					if (ckrv != CKR_OK)
2445 						goto end;
2446 
2447 					ckrv = getObjectLabel(handle,
2448 						(CK_OBJECT_HANDLE)keys[n].keyp,
2449 						&(keys[n].keylabel));
2450 					if (ckrv != CKR_OK)
2451 						goto end;
2452 
2453 					if (keytype == CKK_RSA)
2454 						keys[n].keyalg = KMF_RSA;
2455 					else if (keytype == CKK_DSA)
2456 						keys[n].keyalg = KMF_DSA;
2457 					else if (keytype == CKK_AES)
2458 						keys[n].keyalg = KMF_AES;
2459 					else if (keytype == CKK_RC4)
2460 						keys[n].keyalg = KMF_RC4;
2461 					else if (keytype == CKK_DES)
2462 						keys[n].keyalg = KMF_DES;
2463 					else if (keytype == CKK_DES3)
2464 						keys[n].keyalg = KMF_DES3;
2465 
2466 				}
2467 				n++;
2468 			} else {
2469 				break;
2470 			}
2471 		}
2472 		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2473 
2474 		/* "numkeys" indicates the number that were actually found */
2475 		*numkeys = n;
2476 	}
2477 	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
2478 		if (parms->format == KMF_FORMAT_RAWKEY) {
2479 			/* Convert keys to "rawkey" format */
2480 			for (i = 0; i < (*numkeys); i++) {
2481 				KMF_RAW_KEY_DATA *rkey = NULL;
2482 				rv = keyObj2RawKey(handle, &keys[i], &rkey);
2483 				if (rv == KMF_OK) {
2484 					keys[i].keyp = rkey;
2485 					keys[i].israw = TRUE;
2486 				} else {
2487 					break;
2488 				}
2489 			}
2490 		}
2491 	}
2492 end:
2493 	if (ckrv != CKR_OK) {
2494 		SET_ERROR(kmfh, ckrv);
2495 		/* Report authentication failures to the caller */
2496 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2497 		    ckrv == CKR_PIN_INCORRECT ||
2498 		    ckrv == CKR_PIN_INVALID ||
2499 		    ckrv == CKR_PIN_EXPIRED ||
2500 		    ckrv == CKR_PIN_LOCKED ||
2501 		    ckrv == CKR_SESSION_READ_ONLY)
2502 			rv = KMF_ERR_AUTH_FAILED;
2503 		else
2504 			rv = KMF_ERR_INTERNAL;
2505 	} else if ((*numkeys) == 0) {
2506 		rv = KMF_ERR_KEY_NOT_FOUND;
2507 	}
2508 
2509 	return (rv);
2510 }
2511 
2512 static char *
2513 convertDate(char *fulldate)
2514 {
2515 	struct tm tms;
2516 	char newtime[9];
2517 
2518 	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2519 
2520 	if (tms.tm_year < 69)
2521 		tms.tm_year += 100;
2522 
2523 	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2524 
2525 	newtime[8] = 0;
2526 
2527 	/* memory returned must be freed by the caller */
2528 	return ((char *)strdup(newtime));
2529 }
2530 
2531 KMF_RETURN
2532 KMFPK11_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2533 	KMF_RAW_KEY_DATA *rawkey)
2534 {
2535 	KMF_RETURN rv = KMF_OK;
2536 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2537 	int i;
2538 	CK_RV		ckrv = CKR_OK;
2539 	CK_ATTRIBUTE	templ[32];
2540 	CK_OBJECT_HANDLE keyobj;
2541 	CK_KEY_TYPE	keytype;
2542 	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2543 	CK_BBOOL	cktrue = TRUE;
2544 	CK_DATE		startdate, enddate;
2545 	KMF_DATA	id = {NULL, 0};
2546 	KMF_DATA	subject = {NULL, 0};
2547 	KMF_X509EXT_KEY_USAGE kuext;
2548 	KMF_X509_CERTIFICATE *x509 = NULL;
2549 	CK_BBOOL	kufound;
2550 	char		*notbefore = NULL, *start = NULL;
2551 	char		*notafter = NULL, *end = NULL;
2552 
2553 	if (!kmfh)
2554 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2555 
2556 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2557 		return (KMF_ERR_NO_TOKEN_SELECTED);
2558 
2559 	if (params == NULL || params->certificate == NULL ||
2560 		rawkey == NULL)
2561 		return (KMF_ERR_BAD_PARAMETER);
2562 
2563 	if (rawkey->keytype == KMF_RSA)
2564 		keytype = CKK_RSA;
2565 	else if (rawkey->keytype == KMF_DSA)
2566 		keytype = CKK_DSA;
2567 	else
2568 		return (KMF_ERR_BAD_PARAMETER);
2569 
2570 	rv = pk11_authenticate(handle, &params->cred);
2571 	if (rv != KMF_OK) {
2572 		return (rv);
2573 	}
2574 
2575 	id.Data = NULL;
2576 	id.Length = 0;
2577 	rv = KMF_GetCertIDData(params->certificate, &id);
2578 	if (rv != KMF_OK) {
2579 		goto cleanup;
2580 	}
2581 
2582 	rv = DerDecodeSignedCertificate(
2583 		(const KMF_DATA *)params->certificate, &x509);
2584 	if (rv != KMF_OK) {
2585 		goto cleanup;
2586 	}
2587 
2588 	rv = DerEncodeName(&x509->certificate.subject, &subject);
2589 	if (rv != KMF_OK) {
2590 		goto cleanup;
2591 	}
2592 
2593 	rv = KMF_GetCertStartDateString(handle, params->certificate,
2594 		&notbefore);
2595 	if (rv != KMF_OK) {
2596 		goto cleanup;
2597 	}
2598 	start = convertDate(notbefore);
2599 
2600 	rv = KMF_GetCertEndDateString(handle, params->certificate,
2601 		&notafter);
2602 	if (rv != KMF_OK) {
2603 		goto cleanup;
2604 	}
2605 	end = convertDate(notafter);
2606 
2607 	if ((rv = KMF_GetCertKeyUsageExt(params->certificate, &kuext))
2608 		!= KMF_OK && rv != KMF_ERR_EXTENSION_NOT_FOUND)
2609 		goto cleanup;
2610 
2611 	kufound = (rv == KMF_OK);
2612 	rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND above */
2613 
2614 	i = 0;
2615 	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2616 	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2617 	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2618 	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2619 	SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++;
2620 	SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
2621 
2622 	/*
2623 	 * Only set the KeyUsage stuff if the KU extension was present.
2624 	 */
2625 	if (kufound) {
2626 		CK_BBOOL	condition;
2627 
2628 		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
2629 			B_TRUE : B_FALSE;
2630 		SETATTR(templ, i, CKA_UNWRAP, &condition,
2631 			sizeof (CK_BBOOL)); i++;
2632 		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
2633 			B_TRUE : B_FALSE;
2634 		SETATTR(templ, i, CKA_DECRYPT, &condition,
2635 			sizeof (CK_BBOOL)); i++;
2636 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2637 			B_TRUE : B_FALSE;
2638 		SETATTR(templ, i, CKA_SIGN, &condition,
2639 			sizeof (CK_BBOOL)); i++;
2640 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2641 			B_TRUE : B_FALSE;
2642 		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
2643 			sizeof (CK_BBOOL)); i++;
2644 	}
2645 	if (params->label != NULL) {
2646 		SETATTR(templ, i, CKA_LABEL, params->label,
2647 			strlen(params->label));
2648 		i++;
2649 	}
2650 	if (id.Data != NULL &&
2651 		id.Data != NULL && id.Length > 0) {
2652 		SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2653 		i++;
2654 	}
2655 	if (start != NULL) {
2656 		/*
2657 		 * This make some potentially dangerous assumptions:
2658 		 *  1. that the startdate in the parameter block is
2659 		 * properly formatted as YYYYMMDD
2660 		 *  2. That the CK_DATE structure is always the same.
2661 		 */
2662 		(void) memcpy(&startdate, start, sizeof (CK_DATE));
2663 		SETATTR(templ, i, CKA_START_DATE, &startdate,
2664 			sizeof (startdate));
2665 		i++;
2666 	}
2667 	if (end != NULL) {
2668 		(void) memcpy(&enddate, end, sizeof (CK_DATE));
2669 		SETATTR(templ, i, CKA_END_DATE, &enddate, sizeof (enddate));
2670 		i++;
2671 	}
2672 	if (keytype == CKK_RSA) {
2673 		SETATTR(templ, i, CKA_MODULUS,
2674 			rawkey->rawdata.rsa.mod.val,
2675 			rawkey->rawdata.rsa.mod.len);
2676 		i++;
2677 		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
2678 			rawkey->rawdata.rsa.pubexp.val,
2679 			rawkey->rawdata.rsa.pubexp.len);
2680 		i++;
2681 		if (rawkey->rawdata.rsa.priexp.val != NULL) {
2682 			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
2683 				rawkey->rawdata.rsa.priexp.val,
2684 				rawkey->rawdata.rsa.priexp.len);
2685 			i++;
2686 		}
2687 		if (rawkey->rawdata.rsa.prime1.val != NULL) {
2688 			SETATTR(templ, i, CKA_PRIME_1,
2689 				rawkey->rawdata.rsa.prime1.val,
2690 				rawkey->rawdata.rsa.prime1.len);
2691 			i++;
2692 		}
2693 		if (rawkey->rawdata.rsa.prime2.val != NULL) {
2694 			SETATTR(templ, i, CKA_PRIME_2,
2695 				rawkey->rawdata.rsa.prime2.val,
2696 				rawkey->rawdata.rsa.prime2.len);
2697 			i++;
2698 		}
2699 		if (rawkey->rawdata.rsa.exp1.val != NULL) {
2700 			SETATTR(templ, i, CKA_EXPONENT_1,
2701 				rawkey->rawdata.rsa.exp1.val,
2702 				rawkey->rawdata.rsa.exp1.len);
2703 			i++;
2704 		}
2705 		if (rawkey->rawdata.rsa.exp2.val != NULL) {
2706 			SETATTR(templ, i, CKA_EXPONENT_2,
2707 				rawkey->rawdata.rsa.exp2.val,
2708 				rawkey->rawdata.rsa.exp2.len);
2709 			i++;
2710 		}
2711 		if (rawkey->rawdata.rsa.coef.val != NULL) {
2712 			SETATTR(templ, i, CKA_COEFFICIENT,
2713 				rawkey->rawdata.rsa.coef.val,
2714 				rawkey->rawdata.rsa.coef.len);
2715 			i++;
2716 		}
2717 	} else {
2718 		SETATTR(templ, i, CKA_PRIME,
2719 			rawkey->rawdata.dsa.prime.val,
2720 			rawkey->rawdata.dsa.prime.len);
2721 		i++;
2722 		SETATTR(templ, i, CKA_SUBPRIME,
2723 			rawkey->rawdata.dsa.subprime.val,
2724 			rawkey->rawdata.dsa.subprime.len);
2725 		i++;
2726 		SETATTR(templ, i, CKA_BASE,
2727 			rawkey->rawdata.dsa.base.val,
2728 			rawkey->rawdata.dsa.base.len);
2729 		i++;
2730 		SETATTR(templ, i, CKA_VALUE,
2731 			rawkey->rawdata.dsa.value.val,
2732 			rawkey->rawdata.dsa.value.len);
2733 		i++;
2734 	}
2735 
2736 	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
2737 	if (ckrv != CKR_OK) {
2738 		SET_ERROR(kmfh, ckrv);
2739 
2740 		/* Report authentication failures to the caller */
2741 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2742 		    ckrv == CKR_PIN_INCORRECT ||
2743 		    ckrv == CKR_PIN_INVALID ||
2744 		    ckrv == CKR_PIN_EXPIRED ||
2745 		    ckrv == CKR_PIN_LOCKED ||
2746 		    ckrv == CKR_SESSION_READ_ONLY)
2747 			rv = KMF_ERR_AUTH_FAILED;
2748 		else
2749 			rv = KMF_ERR_INTERNAL;
2750 	}
2751 cleanup:
2752 	KMF_FreeData(&id);
2753 	KMF_FreeData(&subject);
2754 	KMF_FreeSignedCert(x509);
2755 	free(x509);
2756 
2757 	return (rv);
2758 }
2759 
2760 KMF_RETURN
2761 KMFPK11_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
2762 	KMF_KEY_HANDLE *symkey)
2763 {
2764 	KMF_RETURN		rv = KMF_OK;
2765 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2766 	CK_RV			ckrv;
2767 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2768 	CK_OBJECT_HANDLE	keyhandle;
2769 	CK_MECHANISM		keyGenMech;
2770 	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
2771 	CK_ULONG		secKeyType;
2772 	CK_ULONG		secKeyLen;	/* for RC4 and AES */
2773 	CK_BBOOL		true = TRUE;
2774 	CK_BBOOL		false = FALSE;
2775 	CK_ATTRIBUTE		templ[15];
2776 	int i;
2777 
2778 	if (kmfh == NULL)
2779 		return (KMF_ERR_UNINITIALIZED);
2780 
2781 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2782 		return (KMF_ERR_NO_TOKEN_SELECTED);
2783 
2784 	if (params == NULL)
2785 		return (KMF_ERR_BAD_PARAMETER);
2786 
2787 	keyGenMech.pParameter = NULL_PTR;
2788 	keyGenMech.ulParameterLen = 0;
2789 	switch (params->keytype) {
2790 	case KMF_AES:
2791 		keyGenMech.mechanism = CKM_AES_KEY_GEN;
2792 		secKeyType = CKK_AES;
2793 		break;
2794 	case KMF_RC4:
2795 		keyGenMech.mechanism = CKM_RC4_KEY_GEN;
2796 		secKeyType = CKK_RC4;
2797 		break;
2798 	case KMF_DES:
2799 		keyGenMech.mechanism = CKM_DES_KEY_GEN;
2800 		secKeyType = CKK_DES;
2801 		break;
2802 	case KMF_DES3:
2803 		keyGenMech.mechanism = CKM_DES3_KEY_GEN;
2804 		secKeyType = CKK_DES3;
2805 		break;
2806 	default:
2807 		return (KMF_ERR_BAD_KEY_TYPE);
2808 	}
2809 
2810 	i = 0;
2811 	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2812 	i++;
2813 	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2814 	i++;
2815 
2816 	if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
2817 		if ((params->keylength % 8) != 0) {
2818 			return (KMF_ERR_BAD_KEY_SIZE);
2819 		}
2820 		secKeyLen = params->keylength/8;  /* in bytes for RC4/AES */
2821 		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
2822 		    sizeof (secKeyLen));
2823 		i++;
2824 	}
2825 
2826 	if (params->keylabel != NULL) {
2827 		SETATTR(templ, i, CKA_LABEL, params->keylabel,
2828 		    strlen(params->keylabel));
2829 		i++;
2830 	}
2831 
2832 	if (params->pkcs11parms.sensitive == B_TRUE) {
2833 		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2834 	} else {
2835 		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2836 	}
2837 	i++;
2838 
2839 	if (params->pkcs11parms.not_extractable == B_TRUE) {
2840 		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2841 	} else {
2842 		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2843 	}
2844 	i++;
2845 
2846 	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2847 	i++;
2848 	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2849 	i++;
2850 	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
2851 	i++;
2852 	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
2853 	i++;
2854 	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2855 	i++;
2856 	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
2857 	i++;
2858 
2859 	rv = pk11_authenticate(handle, &params->cred);
2860 	if (rv != KMF_OK) {
2861 		return (rv);
2862 	}
2863 
2864 	ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i, &keyhandle);
2865 	if (ckrv != CKR_OK) {
2866 		SET_ERROR(kmfh, ckrv);
2867 		rv = KMF_ERR_KEYGEN_FAILED;
2868 		goto out;
2869 	}
2870 
2871 	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2872 	symkey->keyalg = params->keytype;
2873 	symkey->keyclass = KMF_SYMMETRIC;
2874 	symkey->israw = FALSE;
2875 	symkey->keyp = (void *)keyhandle;
2876 
2877 out:
2878 	return (rv);
2879 }
2880 
2881 
2882 KMF_RETURN
2883 KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2884     KMF_RAW_SYM_KEY *rkey)
2885 {
2886 	KMF_RETURN		rv = KMF_OK;
2887 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2888 
2889 	if (kmfh == NULL)
2890 		return (KMF_ERR_UNINITIALIZED);
2891 
2892 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2893 		return (KMF_ERR_NO_TOKEN_SELECTED);
2894 
2895 	if (symkey == NULL || rkey == NULL)
2896 		return (KMF_ERR_BAD_PARAMETER);
2897 	else if (symkey->keyclass != KMF_SYMMETRIC)
2898 		return (KMF_ERR_BAD_KEY_CLASS);
2899 
2900 	if (symkey->israw) {
2901 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2902 
2903 		if (rawkey == NULL ||
2904 		    rawkey->rawdata.sym.keydata.val == NULL ||
2905 		    rawkey->rawdata.sym.keydata.len == 0)
2906 			return (KMF_ERR_BAD_KEYHANDLE);
2907 
2908 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2909 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2910 			return (KMF_ERR_MEMORY);
2911 		(void) memcpy(rkey->keydata.val,
2912 			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2913 	} else {
2914 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
2915 	}
2916 
2917 	return (rv);
2918 }
2919 
2920 KMF_RETURN
2921 KMFPK11_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2922 	KMF_CREDENTIAL *newpin)
2923 {
2924 	KMF_RETURN	ret = KMF_OK;
2925 	CK_RV		rv = CKR_OK;
2926 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
2927 	CK_SESSION_HANDLE	session = NULL;
2928 
2929 	if (handle == NULL || params == NULL || newpin == NULL)
2930 		return (KMF_ERR_BAD_PARAMETER);
2931 
2932 	rv = C_OpenSession(params->pkcs11parms.slot,
2933 		CKF_SERIAL_SESSION | CKF_RW_SESSION,
2934 		NULL, NULL, &session);
2935 	if (rv != CKR_OK) {
2936 		SET_ERROR(kmfh, rv);
2937 		ret = KMF_ERR_UNINITIALIZED;
2938 		goto end;
2939 	}
2940 
2941 	rv = C_SetPIN(session,
2942 		(CK_BYTE *)params->cred.cred, params->cred.credlen,
2943 		(CK_BYTE *)newpin->cred, newpin->credlen);
2944 
2945 	if (rv != CKR_OK) {
2946 		SET_ERROR(kmfh, rv);
2947 		if (rv == CKR_PIN_INCORRECT ||
2948 		    rv == CKR_PIN_INVALID ||
2949 		    rv == CKR_PIN_EXPIRED ||
2950 		    rv == CKR_PIN_LOCKED)
2951 			ret = KMF_ERR_AUTH_FAILED;
2952 		else
2953 			ret = KMF_ERR_INTERNAL;
2954 	}
2955 end:
2956 	if (session != NULL)
2957 		(void) C_CloseSession(session);
2958 	return (ret);
2959 }
2960 
2961 static KMF_RETURN
2962 create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
2963 	CK_FLAGS wanted_flags)
2964 {
2965 	CK_RV rv;
2966 	KMF_RETURN kmf_rv = KMF_OK;
2967 	CK_SLOT_ID_PTR pSlotList;
2968 	CK_ULONG pulCount;
2969 	CK_MECHANISM_INFO info;
2970 	int i;
2971 
2972 	rv = C_Initialize(NULL);
2973 	if ((rv != CKR_OK) &&
2974 	    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
2975 		kmf_rv = KMF_ERR_UNINITIALIZED;
2976 		goto out;
2977 	}
2978 
2979 	rv = C_GetSlotList(0, NULL, &pulCount);
2980 	if (rv != CKR_OK) {
2981 		kmf_rv = KMF_ERR_UNINITIALIZED;
2982 		goto out;
2983 	}
2984 
2985 	pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
2986 	if (pSlotList == NULL) {
2987 		kmf_rv = KMF_ERR_MEMORY;
2988 		goto out;
2989 	}
2990 
2991 	rv = C_GetSlotList(0, pSlotList, &pulCount);
2992 	if (rv != CKR_OK) {
2993 		kmf_rv = KMF_ERR_UNINITIALIZED;
2994 		goto out;
2995 	}
2996 
2997 	for (i = 0; i < pulCount; i++) {
2998 		rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
2999 		if (rv == CKR_OK && (info.flags & wanted_flags))
3000 			break;
3001 	}
3002 	if (i < pulCount) {
3003 		rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
3004 			NULL, NULL, sessionp);
3005 
3006 		if (rv != CKR_OK) {
3007 			kmf_rv = KMF_ERR_UNINITIALIZED;
3008 		}
3009 	} else {
3010 		kmf_rv = KMF_ERR_UNINITIALIZED;
3011 	}
3012 
3013 out:
3014 	if (pSlotList != NULL)
3015 		free(pSlotList);
3016 	return (kmf_rv);
3017 
3018 }
3019 static KMF_RETURN
3020 verify_data(KMF_HANDLE_T handle,
3021 	KMF_ALGORITHM_INDEX AlgorithmId,
3022 	KMF_X509_SPKI *keyp,
3023 	KMF_DATA *data,
3024 	KMF_DATA *signed_data)
3025 {
3026 	KMF_RETURN ret;
3027 	PKCS_ALGORITHM_MAP *pAlgMap = NULL;
3028 	CK_RV ckRv;
3029 	CK_MECHANISM ckMechanism;
3030 	CK_OBJECT_HANDLE ckKeyHandle;
3031 	KMF_BOOL	bTempKey;
3032 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3033 	CK_SESSION_HANDLE	ckSession = NULL;
3034 
3035 	if (AlgorithmId == KMF_ALGID_NONE)
3036 		return (KMF_ERR_BAD_ALGORITHM);
3037 
3038 	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
3039 		AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
3040 
3041 	if (!pAlgMap)
3042 		return (KMF_ERR_BAD_ALGORITHM);
3043 
3044 	ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
3045 		CKF_VERIFY);
3046 	if (ret != KMF_OK)
3047 		return (ret);
3048 
3049 	/* Fetch the verifying key */
3050 	ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
3051 		pAlgMap->key_type, &ckKeyHandle, &bTempKey);
3052 
3053 	if (ret != KMF_OK) {
3054 		return (ret);
3055 	}
3056 
3057 	ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
3058 	ckMechanism.pParameter = NULL;
3059 	ckMechanism.ulParameterLen = 0;
3060 
3061 	ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
3062 	if (ckRv != CKR_OK) {
3063 		if (bTempKey)
3064 			(void) C_DestroyObject(ckSession, ckKeyHandle);
3065 		SET_ERROR(kmfh, ckRv);
3066 		ret = KMF_ERR_INTERNAL;
3067 		goto cleanup;
3068 	}
3069 
3070 	ckRv = C_Verify(ckSession,
3071 		(CK_BYTE *)data->Data,
3072 			(CK_ULONG)data->Length,
3073 			(CK_BYTE *)signed_data->Data,
3074 			(CK_ULONG)signed_data->Length);
3075 
3076 	if (ckRv != CKR_OK) {
3077 		SET_ERROR(kmfh, ckRv);
3078 		ret = KMF_ERR_INTERNAL;
3079 	}
3080 
3081 cleanup:
3082 	if (bTempKey)
3083 		(void) C_DestroyObject(ckSession, ckKeyHandle);
3084 
3085 	(void) C_CloseSession(ckSession);
3086 
3087 	return (ret);
3088 }
3089 
3090 KMF_RETURN
3091 KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle,
3092 	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
3093 	KMF_DATA *insig, KMF_DATA *SignerCertData)
3094 {
3095 	KMF_RETURN ret = KMF_OK;
3096 	KMF_X509_CERTIFICATE *SignerCert = NULL;
3097 	KMF_X509_SPKI *pubkey;
3098 
3099 	if (handle == NULL || indata == NULL ||
3100 	    indata->Data == NULL || indata->Length == 0 ||
3101 	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
3102 	    SignerCertData == NULL || SignerCertData->Data == NULL ||
3103 	    SignerCertData->Length == 0)
3104 		return (KMF_ERR_BAD_PARAMETER);
3105 
3106 	/* Decode the signer cert so we can get the SPKI data */
3107 	ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
3108 	if (ret != KMF_OK)
3109 		goto cleanup;
3110 
3111 	/* Get the public key info from the signer certificate */
3112 	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
3113 
3114 	/* If no algorithm specified, use the certs signature algorithm */
3115 	if (algid == KMF_ALGID_NONE) {
3116 		algid = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert));
3117 	}
3118 
3119 	if (algid == KMF_ALGID_NONE) {
3120 		ret = KMF_ERR_BAD_ALGORITHM;
3121 	} else {
3122 		ret = verify_data(handle, algid, pubkey, indata, insig);
3123 	}
3124 
3125 cleanup:
3126 	if (SignerCert) {
3127 		KMF_FreeSignedCert(SignerCert);
3128 		free(SignerCert);
3129 	}
3130 
3131 	return (ret);
3132 }
3133