xref: /onnv-gate/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c (revision 3089:8ddeb2ace8aa)
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 2006 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 <oidsalg.h>
36 #include <ber_der.h>
37 #include <algorithm.h>
38 
39 #include <cryptoutil.h>
40 #include <security/cryptoki.h>
41 #include <security/pkcs11.h>
42 
43 #define	SETATTR(t, n, atype, value, size) \
44 	t[n].type = atype; \
45 	t[n].pValue = (CK_BYTE *)value; \
46 	t[n].ulValueLen = (CK_ULONG)size;
47 
48 #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; \
49 	h->lasterr.errcode = c;
50 
51 typedef struct _objlist {
52 	CK_OBJECT_HANDLE handle;
53 	struct _objlist *next;
54 } OBJLIST;
55 
56 static KMF_RETURN
57 search_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
58 	boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
59 
60 static KMF_RETURN
61 keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
62 
63 KMF_RETURN
64 KMFPK11_ConfigureKeystore(KMF_HANDLE_T, KMF_CONFIG_PARAMS *);
65 
66 KMF_RETURN
67 KMFPK11_FindCert(KMF_HANDLE_T,
68 	KMF_FINDCERT_PARAMS *,
69 	KMF_X509_DER_CERT *,
70 	uint32_t *);
71 
72 void
73 KMFPK11_FreeKMFCert(KMF_HANDLE_T,
74 	KMF_X509_DER_CERT *kmf_cert);
75 
76 KMF_RETURN
77 KMFPK11_StoreCert(KMF_HANDLE_T, KMF_STORECERT_PARAMS *, KMF_DATA *);
78 
79 KMF_RETURN
80 KMFPK11_ImportCert(KMF_HANDLE_T, KMF_IMPORTCERT_PARAMS *);
81 
82 KMF_RETURN
83 KMFPK11_DeleteCert(KMF_HANDLE_T, KMF_DELETECERT_PARAMS *);
84 
85 KMF_RETURN
86 KMFPK11_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
87 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
88 
89 KMF_RETURN
90 KMFPK11_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
91 	KMF_KEY_HANDLE *, boolean_t);
92 
93 KMF_RETURN
94 KMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
95 
96 KMF_RETURN
97 KMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
98 	KMF_DATA *, KMF_DATA *);
99 
100 KMF_RETURN
101 KMFPK11_GetErrorString(KMF_HANDLE_T, char **);
102 
103 KMF_RETURN
104 KMFPK11_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
105 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
106 
107 KMF_RETURN
108 KMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
109 	KMF_DATA *, KMF_DATA *);
110 
111 KMF_RETURN
112 KMFPK11_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
113 	KMF_KEY_HANDLE *, uint32_t *);
114 
115 KMF_RETURN
116 KMFPK11_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
117 	KMF_RAW_KEY_DATA *);
118 
119 KMF_RETURN
120 KMFPK11_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
121 	KMF_KEY_HANDLE *);
122 
123 KMF_RETURN
124 KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
125 
126 KMF_RETURN
127 KMFPK11_SetTokenPin(KMF_HANDLE_T, KMF_SETPIN_PARAMS *, KMF_CREDENTIAL *);
128 
129 static
130 KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
131 {
132 	1,			/* Version */
133 	KMFPK11_ConfigureKeystore,
134 	KMFPK11_FindCert,
135 	KMFPK11_FreeKMFCert,
136 	KMFPK11_StoreCert,
137 	KMFPK11_ImportCert,
138 	NULL,			/* ImportCRL */
139 	KMFPK11_DeleteCert,
140 	NULL,			/* DeleteCRL */
141 	KMFPK11_CreateKeypair,
142 	KMFPK11_FindKey,
143 	KMFPK11_EncodePubKeyData,
144 	KMFPK11_SignData,
145 	KMFPK11_DeleteKey,
146 	NULL,			/* ListCRL */
147 	NULL,			/* FindCRL */
148 	NULL,			/* FindCertInCRL */
149 	KMFPK11_GetErrorString,
150 	KMFPK11_GetPrikeyByCert,
151 	KMFPK11_DecryptData,
152 	NULL,			/* ExportP12 */
153 	KMFPK11_StorePrivateKey,
154 	KMFPK11_CreateSymKey,
155 	KMFPK11_GetSymKeyValue,
156 	KMFPK11_SetTokenPin,
157 	NULL			/* Finalize */
158 };
159 
160 KMF_PLUGIN_FUNCLIST *
161 KMF_Plugin_Initialize()
162 {
163 	return (&pk11token_plugin_table);
164 }
165 
166 KMF_RETURN
167 KMFPK11_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
168 {
169 	KMF_RETURN rv = KMF_OK;
170 
171 	if (params == NULL || params->pkcs11config.label == NULL)
172 		return (KMF_ERR_BAD_PARAMETER);
173 
174 	rv = KMF_SelectToken(handle, params->pkcs11config.label,
175 	    params->pkcs11config.readonly);
176 
177 	return (rv);
178 }
179 
180 static KMF_RETURN
181 pk11_authenticate(KMF_HANDLE_T handle,
182 	KMF_CREDENTIAL *cred)
183 {
184 
185 	CK_RV ck_rv = CKR_OK;
186 	CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
187 
188 	if (hSession == NULL)
189 		return (KMF_ERR_NO_TOKEN_SELECTED);
190 
191 	if (cred == NULL || cred->cred == NULL || cred->credlen == 0) {
192 		return (KMF_ERR_BAD_PARAMETER);
193 	}
194 
195 	if ((ck_rv = C_Login(hSession, CKU_USER,
196 		(uchar_t *)cred->cred, cred->credlen)) != CKR_OK) {
197 		if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
198 			handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
199 			handle->lasterr.errcode = ck_rv;
200 			return (KMF_ERR_AUTH_FAILED);
201 		}
202 	}
203 
204 	return (KMF_OK);
205 }
206 
207 static KMF_RETURN
208 PK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
209 		KMF_X509_DER_CERT *kmfcert)
210 {
211 	KMF_RETURN rv = 0;
212 	CK_RV ckrv = CKR_OK;
213 
214 	CK_CERTIFICATE_TYPE cktype;
215 	CK_OBJECT_CLASS	class;
216 	CK_BBOOL	cktrusted, token;
217 	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
218 	CK_BYTE *subject = NULL, *value = NULL;
219 	CK_BYTE *label = NULL;
220 	CK_ULONG label_len = 0;
221 	CK_ATTRIBUTE templ[10];
222 
223 	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
224 
225 	/*  Is this a certificate object ? */
226 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
227 	if (ckrv != CKR_OK || class != CKO_CERTIFICATE)  {
228 		SET_ERROR(kmfh, ckrv);
229 		return (KMF_ERR_INTERNAL);
230 	}
231 
232 	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
233 	SETATTR(templ, 1, CKA_TOKEN, &token, sizeof (token));
234 	SETATTR(templ, 2, CKA_TRUSTED, &cktrusted, sizeof (cktrusted));
235 
236 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 3);
237 
238 	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
239 		SET_ERROR(kmfh, ckrv);
240 		return (ckrv);
241 	} else {
242 		/* What attributes are available and how big are they? */
243 		subject_len = issuer_len = serno_len = id_len = value_len =
244 			label_len = 0;
245 		SETATTR(templ, 0, CKA_SUBJECT,	NULL, subject_len);
246 		SETATTR(templ, 1, CKA_ISSUER,	NULL, issuer_len);
247 		SETATTR(templ, 2, CKA_SERIAL_NUMBER, NULL, serno_len);
248 		SETATTR(templ, 3, CKA_ID, NULL, id_len);
249 		SETATTR(templ, 4, CKA_VALUE, NULL, value_len);
250 		SETATTR(templ, 5, CKA_LABEL, NULL, label_len);
251 
252 		/*
253 		 * Query the object with NULL values in the pValue spot
254 		 * so we know how much space to allocate for each field.
255 		 */
256 		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 6);
257 		if (ckrv != CKR_OK)  {
258 			SET_ERROR(kmfh, ckrv);
259 			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
260 		}
261 
262 		subject_len	= templ[0].ulValueLen;
263 		issuer_len	= templ[1].ulValueLen;
264 		serno_len	= templ[2].ulValueLen;
265 		id_len		= templ[3].ulValueLen;
266 		value_len	= templ[4].ulValueLen;
267 		label_len	= templ[5].ulValueLen;
268 
269 		/*
270 		 * For PKCS#11 CKC_X_509 certificate objects,
271 		 * the following attributes must be defined.
272 		 * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
273 		 * CKA_VALUE.
274 		 */
275 		if (subject_len == 0 || issuer_len == 0 ||
276 		    serno_len == 0 || value_len == 0) {
277 			return (KMF_ERR_INTERNAL);
278 		}
279 
280 		/* Only fetch the value field if we are saving the data */
281 		if (kmfcert != NULL) {
282 			int i = 0;
283 			value = malloc(value_len);
284 			if (value == NULL) {
285 				rv = KMF_ERR_MEMORY;
286 				goto errout;
287 			}
288 
289 			SETATTR(templ, i, CKA_VALUE, value, value_len);
290 			i++;
291 			if (label_len > 0) {
292 				label = malloc(label_len + 1);
293 				if (label == NULL) {
294 					rv = KMF_ERR_MEMORY;
295 					goto errout;
296 				}
297 				(void) memset(label, 0, label_len + 1);
298 				SETATTR(templ, i, CKA_LABEL, label,
299 					label_len);
300 				i++;
301 			}
302 
303 			/* re-query the object with room for the value attr */
304 			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
305 				templ, i);
306 
307 			if (ckrv != CKR_OK)  {
308 				SET_ERROR(kmfh, ckrv);
309 				rv = KMF_ERR_INTERNAL;
310 				goto errout;
311 			}
312 
313 			kmfcert->certificate.Data = value;
314 			kmfcert->certificate.Length = value_len;
315 			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
316 			kmfcert->kmf_private.keystore_type =
317 				KMF_KEYSTORE_PK11TOKEN;
318 			kmfcert->kmf_private.label = (char *)label;
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;
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 		rv = KMF_ERR_ENCODING;
1086 		goto cleanup;
1087 	}
1088 
1089 	/* Generate an ID from the SPKI data */
1090 	rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
1091 			&Id);
1092 
1093 	if (rv != KMF_OK) {
1094 		SET_ERROR(kmfh, rv);
1095 		goto cleanup;
1096 	}
1097 
1098 	i = 0;
1099 	SETATTR(x509templ, i, CKA_CLASS, &certClass,
1100 		sizeof (certClass)); i++;
1101 	SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
1102 		sizeof (certtype)); i++;
1103 	SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
1104 	SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
1105 	SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
1106 	SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
1107 	SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
1108 	SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
1109 	if (label != NULL && strlen(label)) {
1110 		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));
1111 		i++;
1112 	}
1113 
1114 	/*
1115 	 * The cert object handle is actually "leaked" here.  If the app
1116 	 * really wants to clean up the data space, it will have to call
1117 	 * KMF_DeleteCert and specify the softtoken keystore.
1118 	 */
1119 	ckrv = C_CreateObject(kmfh->pk11handle, x509templ, i, &hCert);
1120 	if (ckrv != CKR_OK) {
1121 		SET_ERROR(kmfh, rv);
1122 		rv = KMF_ERR_INTERNAL;
1123 	}
1124 	free(subject);
1125 	free(issuer);
1126 
1127 cleanup:
1128 	if (Id.Data != NULL)
1129 		free(Id.Data);
1130 
1131 	if (signed_cert_ptr) {
1132 		KMF_FreeSignedCert(signed_cert_ptr);
1133 		free(signed_cert_ptr);
1134 	}
1135 	return (rv);
1136 }
1137 
1138 
1139 KMF_RETURN
1140 KMFPK11_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
1141 		KMF_DATA *pcert)
1142 {
1143 	KMF_RETURN rv = 0;
1144 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1145 
1146 	if (!kmfh)
1147 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1148 
1149 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1150 		return (KMF_ERR_NO_TOKEN_SELECTED);
1151 
1152 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1153 		return (KMF_ERR_BAD_PARAMETER);
1154 
1155 	rv = CreateCertObject(handle, params->certLabel, pcert);
1156 	return (rv);
1157 }
1158 
1159 
1160 
1161 KMF_RETURN
1162 KMFPK11_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *params)
1163 {
1164 	KMF_RETURN rv = 0;
1165 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1166 	KMF_ENCODE_FORMAT format;
1167 	KMF_DATA  cert1 = { NULL, 0};
1168 	KMF_DATA  cert2 = { NULL, 0};
1169 
1170 	if (!kmfh)
1171 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1172 
1173 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1174 		return (KMF_ERR_NO_TOKEN_SELECTED);
1175 
1176 	if (params == NULL || params->certfile == NULL) {
1177 		return (KMF_ERR_BAD_PARAMETER);
1178 	}
1179 
1180 	/*
1181 	 * Check if the input cert file is a valid certificate and
1182 	 * auto-detect the file format of it.
1183 	 */
1184 	rv = KMF_IsCertFile(handle, params->certfile, &format);
1185 	if (rv != KMF_OK)
1186 		return (rv);
1187 
1188 	/* Read in the CERT file */
1189 	rv = KMF_ReadInputFile(handle, params->certfile, &cert1);
1190 	if (rv != KMF_OK) {
1191 		return (rv);
1192 	}
1193 
1194 	/*
1195 	 * If the input certificate is in PEM format, we need to convert
1196 	 * it to DER first.
1197 	 */
1198 	if (format == KMF_FORMAT_PEM) {
1199 		int derlen;
1200 		rv = KMF_Pem2Der(cert1.Data, cert1.Length,
1201 		    &cert2.Data, &derlen);
1202 		if (rv != KMF_OK) {
1203 			goto out;
1204 		}
1205 		cert2.Length = (size_t)derlen;
1206 	}
1207 
1208 	rv = CreateCertObject(handle, params->certLabel,
1209 	    format == KMF_FORMAT_ASN1 ? &cert1 : &cert2);
1210 
1211 out:
1212 	if (cert1.Data != NULL) {
1213 		free(cert1.Data);
1214 	}
1215 
1216 	if (cert2.Data != NULL) {
1217 		free(cert2.Data);
1218 	}
1219 
1220 	return (rv);
1221 }
1222 
1223 KMF_RETURN
1224 KMFPK11_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
1225 {
1226 	KMF_RETURN rv = 0;
1227 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1228 	OBJLIST *objlist;
1229 	uint32_t numObjects = 0;
1230 
1231 	if (!kmfh)
1232 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1233 
1234 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1235 		return (KMF_ERR_NO_TOKEN_SELECTED);
1236 
1237 	if (params == NULL)
1238 		return (KMF_ERR_BAD_PARAMETER);
1239 
1240 	/*
1241 	 * Use the same search routine as is used for the FindCert
1242 	 * operation.
1243 	 */
1244 	objlist = NULL;
1245 	rv = search_certs(handle,
1246 		params->certLabel, params->issuer,
1247 		params->subject, params->serial,
1248 		params->pkcs11parms.private,
1249 		params->find_cert_validity,
1250 		&objlist, &numObjects);
1251 
1252 	if (rv == KMF_OK && objlist != NULL) {
1253 		OBJLIST *node = objlist;
1254 
1255 		while (node != NULL) {
1256 			CK_RV ckrv;
1257 			ckrv = C_DestroyObject(kmfh->pk11handle,
1258 				node->handle);
1259 			if (ckrv != CKR_OK) {
1260 				SET_ERROR(kmfh, ckrv);
1261 				rv = KMF_ERR_INTERNAL;
1262 				break;
1263 			}
1264 			node = node->next;
1265 		}
1266 		free_objlist(objlist);
1267 	}
1268 
1269 	if (rv == KMF_OK && numObjects == 0)
1270 		rv = KMF_ERR_CERT_NOT_FOUND;
1271 
1272 out:
1273 	return (rv);
1274 }
1275 
1276 KMF_RETURN
1277 KMFPK11_CreateKeypair(KMF_HANDLE_T handle, KMF_CREATEKEYPAIR_PARAMS *params,
1278 	KMF_KEY_HANDLE *privkey, KMF_KEY_HANDLE *pubkey)
1279 {
1280 	KMF_RETURN rv = KMF_OK;
1281 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1282 
1283 	CK_RV			ckrv = 0;
1284 	CK_OBJECT_HANDLE	pubKey = CK_INVALID_HANDLE;
1285 	CK_OBJECT_HANDLE	priKey = CK_INVALID_HANDLE;
1286 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1287 
1288 	static CK_OBJECT_CLASS	priClass = CKO_PRIVATE_KEY;
1289 	static CK_OBJECT_CLASS	pubClass = CKO_PUBLIC_KEY;
1290 
1291 	static CK_ULONG	rsaKeyType = CKK_RSA;
1292 	static CK_ULONG	modulusBits = 1024;
1293 	static CK_BYTE	PubExpo[3] = {0x01, 0x00, 0x01};
1294 	static CK_BBOOL	true = TRUE;
1295 	static CK_BBOOL	ontoken = TRUE;
1296 	static CK_BBOOL	false = FALSE;
1297 	static CK_ULONG	dsaKeyType = CKK_DSA;
1298 
1299 	CK_ATTRIBUTE rsaPubKeyTemplate[8];
1300 	CK_ATTRIBUTE rsaPriKeyTemplate[6];
1301 
1302 	static CK_BYTE ckDsaPrime[128] = {
1303 	0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
1304 	0xcf, 0xdd, 0xf9, 0xae, 0x3e, 0x39, 0x7f, 0x9c,
1305 	0xa7, 0x73, 0xc3, 0x00, 0xa3, 0x50, 0x67, 0xc3,
1306 	0xab, 0x49, 0x2c, 0xea, 0x59, 0x10, 0xa4, 0xbc,
1307 	0x09, 0x94, 0xa9, 0x05, 0x3b, 0x0d, 0x35, 0x3c,
1308 	0x55, 0x52, 0x47, 0xf0, 0xe3, 0x72, 0x5b, 0xe8,
1309 	0x72, 0xa0, 0x71, 0x1c, 0x23, 0x4f, 0x6d, 0xe8,
1310 	0xac, 0xe5, 0x21, 0x1b, 0xc0, 0xd8, 0x42, 0xd3,
1311 	0x87, 0xae, 0x83, 0x5e, 0x52, 0x7e, 0x46, 0x09,
1312 	0xb5, 0xc7, 0x3d, 0xd6, 0x00, 0xf5, 0xf2, 0x9c,
1313 	0x84, 0x30, 0x81, 0x7e, 0x7b, 0x30, 0x5b, 0xd5,
1314 	0xab, 0xd0, 0x2f, 0x21, 0xb3, 0xd8, 0xed, 0xdb,
1315 	0x97, 0x77, 0xe4, 0x7e, 0x6c, 0xcc, 0xb9, 0x6b,
1316 	0xdd, 0xaa, 0x96, 0x04, 0xe7, 0xd4, 0x55, 0x11,
1317 	0x53, 0xab, 0xba, 0x95, 0x9a, 0xa2, 0x8c, 0x27,
1318 	0xd9, 0xcf, 0xad, 0xf3, 0xcf, 0x3a, 0x0c, 0x4b};
1319 
1320 	static CK_BYTE ckDsaSubPrime[20] = {
1321 	0xa4, 0x5f, 0x2a, 0x27, 0x09, 0x49, 0xb6, 0xfe,
1322 	0x73, 0xeb, 0x95, 0x7d, 0x00, 0xf3, 0x42, 0xfc,
1323 	0x78, 0x47, 0xb0, 0xd5};
1324 
1325 	static CK_BYTE ckDsaBase[128] = {
1326 	0x5c, 0x57, 0x16, 0x49, 0xef, 0xc8, 0xfb, 0x4b,
1327 	0xee, 0x07, 0x45, 0x3b, 0x6a, 0x1d, 0xf3, 0xe5,
1328 	0xeb, 0xee, 0xad, 0x11, 0x13, 0xe3, 0x52, 0xe3,
1329 	0x0d, 0xc0, 0x21, 0x25, 0xfa, 0xf0, 0x93, 0x1c,
1330 	0x53, 0x4d, 0xdc, 0x0d, 0x76, 0xd2, 0xfe, 0xc2,
1331 	0xd7, 0x72, 0x64, 0x69, 0x53, 0x3d, 0x33, 0xbd,
1332 	0xe1, 0x34, 0xf2, 0x5a, 0x67, 0x83, 0xe0, 0xd3,
1333 	0x1c, 0xd6, 0x41, 0x4d, 0x16, 0xe8, 0x6c, 0x5a,
1334 	0x07, 0x95, 0x21, 0x9a, 0xa3, 0xc4, 0xb9, 0x05,
1335 	0x9d, 0x11, 0xcb, 0xc8, 0xc4, 0x9d, 0x00, 0x1a,
1336 	0xf4, 0x85, 0x2a, 0xa9, 0x20, 0x3c, 0xba, 0x67,
1337 	0xe5, 0xed, 0x31, 0xb2, 0x11, 0xfb, 0x1f, 0x73,
1338 	0xec, 0x61, 0x29, 0xad, 0xc7, 0x68, 0xb2, 0x3f,
1339 	0x38, 0xea, 0xd9, 0x87, 0x83, 0x9e, 0x7e, 0x19,
1340 	0x18, 0xdd, 0xc2, 0xc3, 0x5b, 0x16, 0x6d, 0xce,
1341 	0xcf, 0x88, 0x91, 0x07, 0xe0, 0x2b, 0xa8, 0x54 };
1342 
1343 	static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
1344 	{ CKA_CLASS, &pubClass, sizeof (pubClass) },
1345 	{ CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
1346 	{ CKA_TOKEN, &ontoken, sizeof (ontoken)},
1347 	{ CKA_PRIVATE, &false, sizeof (false)},
1348 	{ CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) },
1349 	{ CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)},
1350 	{ CKA_BASE, &ckDsaBase, sizeof (ckDsaBase) },
1351 	{ CKA_VERIFY, &true, sizeof (true) },
1352 };
1353 
1354 #define	NUMBER_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1355 					sizeof (CK_ATTRIBUTE))
1356 #define	MAX_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
1357 				    sizeof (CK_ATTRIBUTE))
1358 
1359 	static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
1360 	{CKA_CLASS, &priClass, sizeof (priClass)},
1361 	{CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
1362 	{CKA_TOKEN, &ontoken, sizeof (ontoken)},
1363 	{CKA_PRIVATE, &true, sizeof (true)},
1364 	{CKA_SIGN, &true, sizeof (true)},
1365 	};
1366 
1367 	CK_ATTRIBUTE labelattr[1];
1368 	CK_ATTRIBUTE idattr[1];
1369 	char IDHashData[SHA1_HASH_LENGTH];
1370 	KMF_DATA IDInput, IDOutput;
1371 
1372 #define	NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1373 					sizeof (CK_ATTRIBUTE))
1374 #define	MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
1375 				sizeof (CK_ATTRIBUTE))
1376 
1377 	if (!kmfh)
1378 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1379 
1380 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1381 		return (KMF_ERR_NO_TOKEN_SELECTED);
1382 
1383 	if (params == NULL)
1384 		return (KMF_ERR_BAD_PARAMETER);
1385 
1386 	rv = pk11_authenticate(handle, &params->cred);
1387 	if (rv != KMF_OK) {
1388 		return (rv);
1389 	}
1390 
1391 	if (params->keytype == KMF_RSA) {
1392 		CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN,
1393 			NULL, 0};
1394 		CK_BYTE *modulus;
1395 		CK_ULONG modulusLength;
1396 		CK_ATTRIBUTE modattr[1];
1397 
1398 		SETATTR(rsaPubKeyTemplate, 0, CKA_CLASS,
1399 			&pubClass, sizeof (pubClass));
1400 		SETATTR(rsaPubKeyTemplate, 1, CKA_KEY_TYPE,
1401 			&rsaKeyType, sizeof (rsaKeyType));
1402 		SETATTR(rsaPubKeyTemplate, 2, CKA_TOKEN,
1403 			&false, sizeof (false));
1404 		SETATTR(rsaPubKeyTemplate, 3, CKA_PRIVATE,
1405 			&false, sizeof (false));
1406 		SETATTR(rsaPubKeyTemplate, 4, CKA_MODULUS_BITS,
1407 			&modulusBits, sizeof (modulusBits));
1408 		if (params->rsa_exponent.len > 0 &&
1409 			params->rsa_exponent.val != NULL) {
1410 			SETATTR(rsaPubKeyTemplate, 5,
1411 				CKA_PUBLIC_EXPONENT,
1412 				params->rsa_exponent.val,
1413 				params->rsa_exponent.len);
1414 		} else {
1415 			SETATTR(rsaPubKeyTemplate, 5,
1416 				CKA_PUBLIC_EXPONENT, &PubExpo,
1417 				sizeof (PubExpo));
1418 		}
1419 		SETATTR(rsaPubKeyTemplate, 6, CKA_ENCRYPT,
1420 			&true, sizeof (true));
1421 		SETATTR(rsaPubKeyTemplate, 7, CKA_VERIFY,
1422 			&true, sizeof (true));
1423 
1424 		SETATTR(rsaPriKeyTemplate, 0, CKA_CLASS, &priClass,
1425 			sizeof (priClass));
1426 		SETATTR(rsaPriKeyTemplate, 1, CKA_KEY_TYPE, &rsaKeyType,
1427 			sizeof (rsaKeyType));
1428 		SETATTR(rsaPriKeyTemplate, 2, CKA_TOKEN, &ontoken,
1429 			sizeof (ontoken));
1430 		SETATTR(rsaPriKeyTemplate, 3, CKA_PRIVATE, &true,
1431 			sizeof (true));
1432 		SETATTR(rsaPriKeyTemplate, 4, CKA_DECRYPT, &true,
1433 			sizeof (true));
1434 		SETATTR(rsaPriKeyTemplate, 5, CKA_SIGN, &true,
1435 			sizeof (true));
1436 
1437 		SETATTR(modattr, 0, CKA_MODULUS, NULL, &modulusLength);
1438 
1439 		modulusBits = params->keylength;
1440 
1441 		pubKey = CK_INVALID_HANDLE;
1442 		priKey = CK_INVALID_HANDLE;
1443 		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1444 			rsaPubKeyTemplate,
1445 			(sizeof (rsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1446 			rsaPriKeyTemplate,
1447 			(sizeof (rsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1448 			&pubKey, &priKey);
1449 		if (ckrv != CKR_OK) {
1450 			SET_ERROR(kmfh, ckrv);
1451 			return (KMF_ERR_KEYGEN_FAILED);
1452 		}
1453 
1454 		if (privkey != NULL) {
1455 			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1456 			privkey->keyalg = KMF_RSA;
1457 			privkey->keyclass = KMF_ASYM_PRI;
1458 			privkey->keyp = (void *)priKey;
1459 		}
1460 		if (pubkey != NULL) {
1461 			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1462 			pubkey->keyalg = KMF_RSA;
1463 			pubkey->keyclass = KMF_ASYM_PUB;
1464 			pubkey->keyp = (void *)pubKey;
1465 		}
1466 
1467 		/* Get the Modulus field to use as input for creating the ID */
1468 		rv = C_GetAttributeValue(kmfh->pk11handle,
1469 			(CK_OBJECT_HANDLE)pubKey,
1470 			modattr, 1);
1471 		if (rv != CKR_OK) {
1472 			SET_ERROR(kmfh, ckrv);
1473 			return (KMF_ERR_BAD_PARAMETER);
1474 		}
1475 
1476 		modulusLength = modattr[0].ulValueLen;
1477 		modulus = malloc(modulusLength);
1478 		if (modulus == NULL)
1479 			return (KMF_ERR_MEMORY);
1480 
1481 		modattr[0].pValue = modulus;
1482 		rv = C_GetAttributeValue(kmfh->pk11handle,
1483 			(CK_OBJECT_HANDLE)pubKey,
1484 			modattr, 1);
1485 		if (rv != CKR_OK) {
1486 			SET_ERROR(kmfh, ckrv);
1487 			free(modulus);
1488 			return (KMF_ERR_BAD_PARAMETER);
1489 		}
1490 
1491 		IDInput.Data = modulus;
1492 		IDInput.Length = modulusLength;
1493 
1494 	} else if (params->keytype == KMF_DSA) {
1495 		CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
1496 		CK_BYTE *keyvalue;
1497 		CK_ULONG valueLen;
1498 		CK_ATTRIBUTE valattr[1];
1499 
1500 		SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
1501 				&ontoken, sizeof (ontoken));
1502 		SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen);
1503 
1504 		ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
1505 			ckDsaPubKeyTemplate,
1506 			(sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1507 			ckDsaPriKeyTemplate,
1508 			(sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
1509 			&pubKey, &priKey);
1510 		if (ckrv != CKR_OK) {
1511 			SET_ERROR(kmfh, ckrv);
1512 			return (KMF_ERR_KEYGEN_FAILED);
1513 		}
1514 
1515 		if (privkey != NULL) {
1516 			privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1517 			privkey->keyalg = KMF_DSA;
1518 			privkey->keyclass = KMF_ASYM_PRI;
1519 			privkey->keyp = (void *)priKey;
1520 		}
1521 		if (pubkey != NULL) {
1522 			pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
1523 			pubkey->keyalg = KMF_DSA;
1524 			pubkey->keyclass = KMF_ASYM_PUB;
1525 			pubkey->keyp = (void *)pubKey;
1526 		}
1527 		/* Get the Public Value to use as input for creating the ID */
1528 		rv = C_GetAttributeValue(hSession,
1529 			(CK_OBJECT_HANDLE)pubKey,
1530 			valattr, 1);
1531 		if (rv != CKR_OK) {
1532 			SET_ERROR(kmfh, ckrv);
1533 			return (KMF_ERR_BAD_PARAMETER);
1534 		}
1535 
1536 		valueLen = valattr[0].ulValueLen;
1537 		keyvalue = malloc(valueLen);
1538 		if (keyvalue == NULL)
1539 			return (KMF_ERR_MEMORY);
1540 
1541 		valattr[0].pValue = keyvalue;
1542 		rv = C_GetAttributeValue(hSession,
1543 			(CK_OBJECT_HANDLE)pubKey,
1544 			valattr, 1);
1545 		if (rv != CKR_OK) {
1546 			SET_ERROR(kmfh, ckrv);
1547 			free(keyvalue);
1548 			return (KMF_ERR_BAD_PARAMETER);
1549 		}
1550 
1551 		IDInput.Data = keyvalue;
1552 		IDInput.Length = valueLen;
1553 	} else {
1554 		return (KMF_ERR_BAD_PARAMETER);
1555 	}
1556 
1557 	if (params->keylabel != NULL &&
1558 		strlen(params->keylabel)) {
1559 
1560 		SETATTR(labelattr, 0, CKA_LABEL, params->keylabel,
1561 			strlen(params->keylabel));
1562 
1563 		/* Set the CKA_LABEL if one was indicated */
1564 		if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1565 			labelattr, 1)) != CKR_OK) {
1566 			SET_ERROR(kmfh, ckrv);
1567 			rv = KMF_ERR_INTERNAL;
1568 			goto cleanup;
1569 		}
1570 		if (pubkey != NULL) {
1571 			pubkey->keylabel =
1572 				(char *)strdup(params->keylabel);
1573 			if (pubkey->keylabel == NULL) {
1574 				rv = KMF_ERR_MEMORY;
1575 				goto cleanup;
1576 			}
1577 		}
1578 		if ((ckrv = C_SetAttributeValue(hSession, priKey,
1579 			labelattr, 1)) != CKR_OK) {
1580 			SET_ERROR(kmfh, ckrv);
1581 			rv = KMF_ERR_INTERNAL;
1582 			goto cleanup;
1583 		}
1584 		if (privkey != NULL) {
1585 			privkey->keylabel =
1586 				(char *)strdup(params->keylabel);
1587 			if (privkey->keylabel == NULL) {
1588 				rv = KMF_ERR_MEMORY;
1589 				goto cleanup;
1590 			}
1591 		}
1592 	}
1593 
1594 	/* Now, assign a CKA_ID value so it can be searched */
1595 	/* ID_Input was assigned above in the RSA or DSA keygen section */
1596 	IDOutput.Data = (uchar_t *)IDHashData;
1597 	IDOutput.Length = sizeof (IDHashData);
1598 
1599 	rv = DigestData(hSession, &IDInput, &IDOutput);
1600 	free(IDInput.Data);
1601 
1602 	if (rv != CKR_OK) {
1603 		SET_ERROR(kmfh, rv);
1604 		goto cleanup;
1605 	}
1606 	SETATTR(idattr, 0, CKA_ID, IDOutput.Data, IDOutput.Length);
1607 	if ((ckrv = C_SetAttributeValue(hSession, pubKey,
1608 			idattr, 1)) != CKR_OK) {
1609 		SET_ERROR(kmfh, ckrv);
1610 		rv = KMF_ERR_INTERNAL;
1611 		goto cleanup;
1612 	}
1613 	if ((ckrv = C_SetAttributeValue(hSession, priKey,
1614 			idattr, 1)) != CKR_OK) {
1615 		SET_ERROR(kmfh, ckrv);
1616 		rv = KMF_ERR_INTERNAL;
1617 		goto cleanup;
1618 	}
1619 
1620 cleanup:
1621 	if (rv != KMF_OK) {
1622 		if (pubKey != CK_INVALID_HANDLE)
1623 			(void) C_DestroyObject(hSession, pubKey);
1624 		if (priKey != CK_INVALID_HANDLE)
1625 			(void) C_DestroyObject(hSession, priKey);
1626 		if (privkey) {
1627 			privkey->keyp = NULL;
1628 			if (privkey->keylabel)
1629 				free(privkey->keylabel);
1630 		}
1631 		if (pubkey) {
1632 			pubkey->keyp = NULL;
1633 			if (pubkey->keylabel)
1634 				free(pubkey->keylabel);
1635 		}
1636 	}
1637 	return (rv);
1638 }
1639 
1640 KMF_RETURN
1641 KMFPK11_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1642 	KMF_KEY_HANDLE *key, boolean_t destroy)
1643 {
1644 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1645 	CK_RV ckrv = CKR_OK;
1646 	KMF_RETURN rv = KMF_OK;
1647 
1648 	if (!kmfh)
1649 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1650 
1651 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1652 		return (KMF_ERR_NO_TOKEN_SELECTED);
1653 
1654 	if (key == NULL || key->keyp == NULL)
1655 		return (KMF_ERR_BAD_PARAMETER);
1656 
1657 	if (key->keyclass != KMF_ASYM_PUB &&
1658 		key->keyclass != KMF_ASYM_PRI &&
1659 		key->keyclass != KMF_SYMMETRIC)
1660 		return (KMF_ERR_BAD_KEY_CLASS);
1661 
1662 	if (destroy) {
1663 		rv = pk11_authenticate(handle, &params->cred);
1664 		if (rv != KMF_OK) {
1665 			return (rv);
1666 		}
1667 	}
1668 
1669 	if (!key->israw && destroy)
1670 		ckrv = C_DestroyObject(kmfh->pk11handle,
1671 			(CK_OBJECT_HANDLE)key->keyp);
1672 
1673 	if (ckrv != CKR_OK) {
1674 		SET_ERROR(kmfh, ckrv);
1675 		/* Report authentication failures to the caller */
1676 		if (ckrv == CKR_PIN_EXPIRED ||
1677 		    ckrv == CKR_SESSION_READ_ONLY)
1678 			rv = KMF_ERR_AUTH_FAILED;
1679 		else
1680 			rv = KMF_ERR_INTERNAL;
1681 	}
1682 	return (rv);
1683 
1684 }
1685 
1686 KMF_RETURN
1687 KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1688 	KMF_OID *algOID,
1689 	KMF_DATA *tobesigned,
1690 	KMF_DATA *output)
1691 {
1692 	CK_RV			ckrv;
1693 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1694 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1695 	CK_MECHANISM		mechanism;
1696 	PKCS_ALGORITHM_MAP 	*pAlgMap;
1697 	KMF_ALGORITHM_INDEX		AlgId;
1698 
1699 	if (!kmfh)
1700 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1701 
1702 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1703 		return (KMF_ERR_NO_TOKEN_SELECTED);
1704 
1705 	if (keyp == NULL || algOID == NULL ||
1706 	    tobesigned == NULL || output == NULL)
1707 		return (KMF_ERR_BAD_PARAMETER);
1708 
1709 	/* These functions are available to the plugin from libkmf */
1710 	AlgId = X509_AlgorithmOidToAlgId(algOID);
1711 	if (AlgId == KMF_ALGID_NONE)
1712 		return (KMF_ERR_BAD_PARAMETER);
1713 
1714 	/* Map the Algorithm OID to a PKCS#11 mechanism */
1715 	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1716 		AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1717 
1718 	if (pAlgMap == NULL)
1719 		return (KMF_ERR_BAD_PARAMETER);
1720 
1721 	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1722 	mechanism.pParameter = NULL;
1723 	mechanism.ulParameterLen = 0;
1724 
1725 	ckrv = C_SignInit(hSession, &mechanism, (CK_OBJECT_HANDLE)keyp->keyp);
1726 	if (ckrv != CKR_OK) {
1727 		SET_ERROR(kmfh, ckrv);
1728 		return (KMF_ERR_INTERNAL);
1729 	}
1730 
1731 	ckrv = C_Sign(hSession,
1732 		tobesigned->Data, tobesigned->Length,
1733 		output->Data, (CK_ULONG *)&output->Length);
1734 
1735 	if (ckrv != CKR_OK) {
1736 		SET_ERROR(kmfh, ckrv);
1737 		return (KMF_ERR_INTERNAL);
1738 	}
1739 
1740 	return (KMF_OK);
1741 }
1742 
1743 KMF_RETURN
1744 KMFPK11_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1745 {
1746 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1747 
1748 	*msgstr = NULL;
1749 	if (kmfh->lasterr.errcode != 0) {
1750 		char *e = pkcs11_strerror(kmfh->lasterr.errcode);
1751 		if (e == NULL || (*msgstr = (char *)strdup(e)) == NULL) {
1752 			return (KMF_ERR_MEMORY);
1753 		}
1754 	}
1755 
1756 	return (KMF_OK);
1757 }
1758 
1759 static CK_RV
1760 getObjectKeytype(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1761 	CK_ULONG *keytype)
1762 {
1763 	CK_RV rv = CKR_OK;
1764 	CK_ATTRIBUTE templ;
1765 	CK_ULONG len = sizeof (CK_ULONG);
1766 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1767 
1768 	templ.type = CKA_KEY_TYPE;
1769 	templ.pValue = keytype;
1770 	templ.ulValueLen = len;
1771 
1772 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1773 
1774 	return (rv);
1775 
1776 }
1777 static CK_RV
1778 getObjectLabel(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
1779 	char **outlabel)
1780 {
1781 	CK_RV rv = CKR_OK;
1782 	CK_ATTRIBUTE templ;
1783 	char	Label[BUFSIZ];
1784 	CK_ULONG len = sizeof (Label);
1785 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1786 
1787 	(void) memset(Label, 0, len);
1788 	templ.type = CKA_LABEL;
1789 	templ.pValue = Label;
1790 	templ.ulValueLen = len;
1791 
1792 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
1793 	if (rv == CKR_OK) {
1794 		*outlabel = (char *)strdup(Label);
1795 	} else {
1796 		*outlabel = NULL;
1797 	}
1798 	return (rv);
1799 }
1800 
1801 KMF_RETURN
1802 KMFPK11_GetPrikeyByCert(KMF_HANDLE_T handle,
1803 	KMF_CRYPTOWITHCERT_PARAMS *params,
1804 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
1805 	KMF_KEY_ALG keytype)
1806 {
1807 	KMF_X509_SPKI *pubkey;
1808 	KMF_X509_CERTIFICATE *SignerCert = NULL;
1809 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1810 	KMF_RETURN rv = KMF_OK;
1811 	CK_RV ckrv = CKR_OK;
1812 	CK_ATTRIBUTE templ[4];
1813 	CK_OBJECT_HANDLE pri_obj = CK_INVALID_HANDLE;
1814 	CK_ULONG obj_count;
1815 	CK_OBJECT_CLASS certClass = CKO_PRIVATE_KEY;
1816 	CK_BBOOL true = TRUE;
1817 	KMF_DATA Id = { NULL, 0 };
1818 
1819 	/* Decode the signer cert so we can get the SPKI data */
1820 	if ((rv = DerDecodeSignedCertificate(SignerCertData,
1821 	    &SignerCert)) != KMF_OK)
1822 		return (rv);
1823 
1824 	/* Get the public key info from the signer certificate */
1825 	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
1826 
1827 	/* Generate an ID from the SPKI data */
1828 	rv = GetIDFromSPKI(pubkey, &Id);
1829 
1830 	if (rv != KMF_OK) {
1831 		SET_ERROR(kmfh, rv);
1832 		goto errout;
1833 	}
1834 
1835 	SETATTR(templ, 0, CKA_CLASS, &certClass, sizeof (certClass));
1836 	SETATTR(templ, 1, CKA_TOKEN, &true, sizeof (true));
1837 	SETATTR(templ, 2, CKA_PRIVATE, &true, sizeof (true));
1838 	SETATTR(templ, 3, CKA_ID, Id.Data, Id.Length);
1839 
1840 	rv = pk11_authenticate(handle, &params->cred);
1841 	if (rv != KMF_OK) {
1842 		return (rv);
1843 	}
1844 
1845 	if ((ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, 4)) != CKR_OK) {
1846 		SET_ERROR(kmfh, ckrv);
1847 		rv = KMF_ERR_INTERNAL;
1848 		goto errout;
1849 	}
1850 
1851 	if ((rv = C_FindObjects(kmfh->pk11handle, &pri_obj, 1,
1852 	    &obj_count)) != CKR_OK) {
1853 		SET_ERROR(kmfh, ckrv);
1854 		rv = KMF_ERR_INTERNAL;
1855 		goto errout;
1856 	}
1857 
1858 	if (obj_count == 0) {
1859 		SET_ERROR(kmfh, ckrv);
1860 		rv = KMF_ERR_INTERNAL;
1861 		goto errout;
1862 	}
1863 
1864 	key->kstype = KMF_KEYSTORE_PK11TOKEN;
1865 	key->keyclass = KMF_ASYM_PRI;
1866 	key->keyalg = keytype;
1867 	key->keyp = (void *)pri_obj;
1868 
1869 	(void) C_FindObjectsFinal(kmfh->pk11handle);
1870 
1871 	ckrv = getObjectLabel(handle, (CK_OBJECT_HANDLE)key->keyp,
1872 		&key->keylabel);
1873 
1874 	if (ckrv != CKR_OK) {
1875 		SET_ERROR(handle, ckrv);
1876 		rv = KMF_ERR_INTERNAL;
1877 	} else {
1878 		rv = KMF_OK;
1879 	}
1880 
1881 	if (rv == KMF_OK && params->format == KMF_FORMAT_RAWKEY) {
1882 		KMF_RAW_KEY_DATA *rkey = NULL;
1883 		rv = keyObj2RawKey(handle, key, &rkey);
1884 		if (rv == KMF_OK) {
1885 			key->keyp = rkey;
1886 			key->israw = TRUE;
1887 		}
1888 	}
1889 
1890 errout:
1891 	if (Id.Data != NULL)
1892 		free(Id.Data);
1893 
1894 	if (SignerCert != NULL) {
1895 		KMF_FreeSignedCert(SignerCert);
1896 		free(SignerCert);
1897 	}
1898 	return (rv);
1899 }
1900 
1901 KMF_RETURN
1902 KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1903 	KMF_OID *algOID, KMF_DATA *ciphertext,
1904 	KMF_DATA *output)
1905 {
1906 	CK_RV			ckrv;
1907 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1908 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
1909 	CK_MECHANISM		mechanism;
1910 	PKCS_ALGORITHM_MAP 	*pAlgMap;
1911 	KMF_ALGORITHM_INDEX	AlgId;
1912 	CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
1913 	uint8_t *in_data, *out_data;
1914 	int i, blocks;
1915 	CK_ATTRIBUTE ckTemplate[1];
1916 
1917 	if (!kmfh)
1918 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
1919 
1920 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1921 		return (KMF_ERR_NO_TOKEN_SELECTED);
1922 
1923 	if (key == NULL || algOID == NULL ||
1924 	    ciphertext == NULL || output == NULL)
1925 		return (KMF_ERR_BAD_PARAMETER);
1926 
1927 	AlgId = X509_AlgorithmOidToAlgId(algOID);
1928 	if (AlgId == KMF_ALGID_NONE)
1929 		return (KMF_ERR_BAD_PARAMETER);
1930 
1931 	/* Map the Algorithm ID to a PKCS#11 mechanism */
1932 	pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
1933 	    AlgId, PKCS_GetDefaultSignatureMode(AlgId));
1934 
1935 	if (pAlgMap == NULL)
1936 		return (KMF_ERR_BAD_PARAMETER);
1937 
1938 	mechanism.mechanism = pAlgMap->pkcs_mechanism;
1939 	mechanism.pParameter = NULL;
1940 	mechanism.ulParameterLen = 0;
1941 
1942 	SETATTR(ckTemplate, 0, CKA_MODULUS, (CK_BYTE *)NULL,
1943 	    sizeof (CK_ULONG));
1944 
1945 	/* Get the modulus length */
1946 	ckrv = C_GetAttributeValue(hSession,
1947 	    (CK_OBJECT_HANDLE)key->keyp, ckTemplate, 1);
1948 
1949 	if (ckrv != CKR_OK)  {
1950 		SET_ERROR(kmfh, ckrv);
1951 		return (KMF_ERR_INTERNAL);
1952 	}
1953 
1954 	block_len = ckTemplate[0].ulValueLen;
1955 
1956 	/* Compute the number of times to do single-part decryption */
1957 	blocks = ciphertext->Length/block_len;
1958 
1959 	out_data = output->Data;
1960 	in_data = ciphertext->Data;
1961 	out_len = block_len - 11;
1962 
1963 	for (i = 0; i < blocks; i++) {
1964 		ckrv = C_DecryptInit(hSession, &mechanism,
1965 			(CK_OBJECT_HANDLE)key->keyp);
1966 
1967 		if (ckrv != CKR_OK) {
1968 			SET_ERROR(kmfh, ckrv);
1969 			return (KMF_ERR_INTERNAL);
1970 		}
1971 
1972 		ckrv = C_Decrypt(hSession, in_data, block_len,
1973 		    out_data, (CK_ULONG *)&out_len);
1974 
1975 		if (ckrv != CKR_OK) {
1976 			SET_ERROR(kmfh, ckrv);
1977 			return (KMF_ERR_INTERNAL);
1978 		}
1979 
1980 		out_data += out_len;
1981 		total_decrypted += out_len;
1982 		in_data += block_len;
1983 
1984 	}
1985 
1986 	output->Length = total_decrypted;
1987 	return (KMF_OK);
1988 }
1989 
1990 static void
1991 attr2bigint(CK_ATTRIBUTE_PTR attr, KMF_BIGINT *big)
1992 {
1993 	big->val = attr->pValue;
1994 	big->len = attr->ulValueLen;
1995 }
1996 
1997 
1998 static KMF_RETURN
1999 get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2000 {
2001 	KMF_RETURN rv = KMF_OK;
2002 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2003 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
2004 		{ CKA_MODULUS, NULL, 0 },
2005 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
2006 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
2007 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
2008 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
2009 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
2010 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
2011 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
2012 	    };
2013 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2014 	int		i;
2015 
2016 	if ((rv = C_GetAttributeValue(sess, obj,
2017 			rsa_pri_attrs, count)) != CKR_OK) {
2018 		SET_ERROR(kmfh, rv);
2019 		return (KMF_ERR_INTERNAL);
2020 	}
2021 
2022 	/* Allocate memory for each attribute. */
2023 	for (i = 0; i < count; i++) {
2024 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2025 		    rsa_pri_attrs[i].ulValueLen == 0) {
2026 			rsa_pri_attrs[i].ulValueLen = 0;
2027 			continue;
2028 		}
2029 		if ((rsa_pri_attrs[i].pValue =
2030 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2031 			rv = KMF_ERR_MEMORY;
2032 			goto end;
2033 		}
2034 	}
2035 	/* Now that we have space, really get the attributes */
2036 	if ((rv = C_GetAttributeValue(sess, obj,
2037 			rsa_pri_attrs, count)) != CKR_OK) {
2038 		SET_ERROR(kmfh, rv);
2039 		rv = KMF_ERR_INTERNAL;
2040 		goto end;
2041 	}
2042 	i = 0;
2043 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2044 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2045 
2046 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2047 	    rsa_pri_attrs[i].ulValueLen != 0)
2048 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->priexp);
2049 	i++;
2050 
2051 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2052 	    rsa_pri_attrs[i].ulValueLen != 0)
2053 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime1);
2054 	i++;
2055 
2056 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2057 	    rsa_pri_attrs[i].ulValueLen != 0)
2058 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime2);
2059 	i++;
2060 
2061 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2062 	    rsa_pri_attrs[i].ulValueLen != 0)
2063 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp1);
2064 	i++;
2065 
2066 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2067 	    rsa_pri_attrs[i].ulValueLen != 0)
2068 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp2);
2069 	i++;
2070 
2071 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2072 	    rsa_pri_attrs[i].ulValueLen != 0)
2073 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->coef);
2074 	i++;
2075 
2076 end:
2077 	if (rv != KMF_OK) {
2078 		for (i = 0; i < count; i++) {
2079 			if (rsa_pri_attrs[i].pValue != NULL)
2080 				free(rsa_pri_attrs[i].pValue);
2081 		}
2082 		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2083 	}
2084 	return (rv);
2085 }
2086 
2087 static KMF_RETURN
2088 get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2089 {
2090 	KMF_RETURN rv = KMF_OK;
2091 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2092 	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2093 		{ CKA_PRIME, NULL, 0 },
2094 		{ CKA_SUBPRIME, NULL, 0 },
2095 		{ CKA_BASE, NULL, 0 },
2096 		{ CKA_VALUE, NULL, 0 }
2097 	};
2098 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2099 	int		i;
2100 
2101 	if ((rv = C_GetAttributeValue(sess, obj,
2102 		dsa_pri_attrs, count)) != CKR_OK) {
2103 		SET_ERROR(kmfh, rv);
2104 		return (KMF_ERR_INTERNAL);
2105 	}
2106 
2107 	/* Allocate memory for each attribute. */
2108 	for (i = 0; i < count; i++) {
2109 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2110 		    dsa_pri_attrs[i].ulValueLen == 0) {
2111 			dsa_pri_attrs[i].ulValueLen = 0;
2112 			continue;
2113 		}
2114 		if ((dsa_pri_attrs[i].pValue =
2115 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2116 			rv = KMF_ERR_MEMORY;
2117 			goto end;
2118 		}
2119 	}
2120 	if ((rv = C_GetAttributeValue(sess, obj,
2121 		dsa_pri_attrs, count)) != CKR_OK) {
2122 		SET_ERROR(kmfh, rv);
2123 		rv = KMF_ERR_INTERNAL;
2124 		goto end;
2125 	}
2126 
2127 	/* Fill in all the temp variables.  They are all required. */
2128 	i = 0;
2129 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2130 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2131 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2132 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2133 
2134 end:
2135 	if (rv != KMF_OK) {
2136 		for (i = 0; i < count; i++) {
2137 			if (dsa_pri_attrs[i].pValue != NULL)
2138 				free(dsa_pri_attrs[i].pValue);
2139 		}
2140 		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2141 	}
2142 	return (rv);
2143 }
2144 
2145 static KMF_RETURN
2146 get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2147 {
2148 	KMF_RETURN rv = KMF_OK;
2149 	CK_RV	ckrv;
2150 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2151 	CK_ATTRIBUTE	sym_attr[1];
2152 	CK_ULONG	value_len = 0;
2153 
2154 	/* find the key length first */
2155 	sym_attr[0].type = CKA_VALUE;
2156 	sym_attr[0].pValue = NULL;
2157 	sym_attr[0].ulValueLen = value_len;
2158 	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2159 		/*
2160 		 * Don't return error if the key is sensitive, just
2161 		 * don't return any raw data.  Operations like "list"
2162 		 * need to succeed even if the raw data is not
2163 		 * available.
2164 		 */
2165 		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2166 			rawsym->keydata.val = NULL;
2167 			rawsym->keydata.len = 0;
2168 			return (CKR_OK);
2169 		}
2170 		SET_ERROR(kmfh, ckrv);
2171 		return (KMF_ERR_INTERNAL);
2172 	}
2173 
2174 	/* Allocate memory for pValue */
2175 	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2176 	if (sym_attr[0].pValue == NULL) {
2177 		return (KMF_ERR_MEMORY);
2178 	}
2179 
2180 	/* get the key data */
2181 	if ((rv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2182 		SET_ERROR(kmfh, rv);
2183 		free(sym_attr[0].pValue);
2184 		return (KMF_ERR_INTERNAL);
2185 	}
2186 
2187 	rawsym->keydata.val = sym_attr[0].pValue;
2188 	rawsym->keydata.len = sym_attr[0].ulValueLen;
2189 	return (rv);
2190 }
2191 
2192 static KMF_RETURN
2193 keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2194 	KMF_RAW_KEY_DATA **outkey)
2195 {
2196 	KMF_RETURN rv = KMF_OK;
2197 	KMF_RAW_KEY_DATA *rkey;
2198 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2199 
2200 	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2201 	if (rkey == NULL)
2202 		return (KMF_ERR_MEMORY);
2203 
2204 	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2205 
2206 	rkey->keytype = inkey->keyalg;
2207 
2208 	if (inkey->keyalg == KMF_RSA) {
2209 		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2210 			&rkey->rawdata.rsa);
2211 	} else if (inkey->keyalg == KMF_DSA) {
2212 		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2213 			&rkey->rawdata.dsa);
2214 	} else if (inkey->keyalg == KMF_AES ||
2215 	    inkey->keyalg == KMF_RC4 ||
2216 	    inkey->keyalg == KMF_DES ||
2217 	    inkey->keyalg == KMF_DES3) {
2218 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2219 		    &rkey->rawdata.sym);
2220 	} else {
2221 		rv = KMF_ERR_BAD_PARAMETER;
2222 	}
2223 
2224 	if (rv == KMF_OK) {
2225 		*outkey = rkey;
2226 	} else if (rkey != NULL) {
2227 		free(rkey);
2228 		*outkey = NULL;
2229 	}
2230 
2231 	return (rv);
2232 }
2233 
2234 
2235 static KMF_RETURN
2236 kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2237 {
2238 	switch (keyalg) {
2239 	case KMF_RSA:
2240 		*type = CKK_RSA;
2241 		break;
2242 	case KMF_DSA:
2243 		*type = CKK_DSA;
2244 		break;
2245 	case KMF_AES:
2246 		*type = CKK_AES;
2247 		break;
2248 	case KMF_RC4:
2249 		*type = CKK_RC4;
2250 		break;
2251 	case KMF_DES:
2252 		*type = CKK_DES;
2253 		break;
2254 	case KMF_DES3:
2255 		*type = CKK_DES3;
2256 		break;
2257 	default:
2258 		return (KMF_ERR_BAD_KEY_TYPE);
2259 	}
2260 
2261 	return (KMF_OK);
2262 }
2263 
2264 static int
2265 IDStringToData(char *idstr, KMF_DATA *iddata)
2266 {
2267 	int len, i;
2268 	char *iddup, *byte;
2269 	uint_t lvalue;
2270 
2271 	if (idstr == NULL || !strlen(idstr))
2272 		return (-1);
2273 
2274 	iddup = (char *)strdup(idstr);
2275 	if (iddup == NULL)
2276 		return (KMF_ERR_MEMORY);
2277 
2278 	len = strlen(iddup) / 3  + 1;
2279 	iddata->Data = malloc(len);
2280 	if (iddata->Data == NULL)
2281 		return (KMF_ERR_MEMORY);
2282 	(void) memset(iddata->Data, 0, len);
2283 	iddata->Length = len;
2284 
2285 	byte = strtok(iddup, ":");
2286 	if (byte == NULL) {
2287 		free(iddup);
2288 		free(iddata->Data);
2289 		iddata->Data = NULL;
2290 		iddata->Length = 0;
2291 		return (-1);
2292 	}
2293 
2294 	i = 0;
2295 	do {
2296 		(void) sscanf(byte, "%x", &lvalue);
2297 		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2298 		byte = strtok(NULL, ":");
2299 	} while (byte != NULL && i < len);
2300 
2301 	iddata->Length = i;
2302 	free(iddup);
2303 	return (0);
2304 }
2305 
2306 KMF_RETURN
2307 KMFPK11_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
2308 	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
2309 {
2310 	KMF_RETURN rv = KMF_OK;
2311 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2312 	uint32_t want_keys, i;
2313 	CK_RV ckrv;
2314 	CK_ATTRIBUTE pTmpl[10];
2315 	CK_OBJECT_CLASS class;
2316 	CK_BBOOL true = TRUE;
2317 	CK_BBOOL false = FALSE;
2318 	CK_ULONG alg;
2319 	CK_BBOOL is_token;
2320 
2321 	if (!kmfh)
2322 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2323 
2324 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2325 		return (KMF_ERR_NO_TOKEN_SELECTED);
2326 
2327 	if (parms == NULL || numkeys == NULL)
2328 		return (KMF_ERR_BAD_PARAMETER);
2329 
2330 	if (numkeys != NULL && *numkeys > 0)
2331 		want_keys = *numkeys;
2332 	else
2333 		want_keys = MAXINT; /* count them all */
2334 
2335 	if (parms->keyclass == KMF_ASYM_PUB) {
2336 		class = CKO_PUBLIC_KEY;
2337 		is_token = false;
2338 	} else if (parms->keyclass == KMF_ASYM_PRI) {
2339 		class = CKO_PRIVATE_KEY;
2340 		is_token = true;
2341 	} else if (parms->keyclass == KMF_SYMMETRIC) {
2342 		class = CKO_SECRET_KEY;
2343 		is_token = true;
2344 	} else {
2345 		return (KMF_ERR_BAD_KEY_CLASS);
2346 	}
2347 
2348 	i = 0;
2349 	pTmpl[i].type = CKA_TOKEN;
2350 	pTmpl[i].pValue = &is_token;
2351 	pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
2352 	i++;
2353 
2354 	pTmpl[i].type = CKA_CLASS;
2355 	pTmpl[i].pValue = &class;
2356 	pTmpl[i].ulValueLen = sizeof (class);
2357 	i++;
2358 
2359 	if (parms->findLabel != NULL && strlen(parms->findLabel)) {
2360 		pTmpl[i].type = CKA_LABEL;
2361 		pTmpl[i].pValue = parms->findLabel;
2362 		pTmpl[i].ulValueLen = strlen(parms->findLabel);
2363 		i++;
2364 	}
2365 
2366 	if (parms->keytype != 0) {
2367 		rv = kmf2pk11keytype(parms->keytype, &alg);
2368 		if (rv != KMF_OK) {
2369 			return (KMF_ERR_BAD_KEY_TYPE);
2370 		}
2371 		pTmpl[i].type = CKA_KEY_TYPE;
2372 		pTmpl[i].pValue = &alg;
2373 		pTmpl[i].ulValueLen = sizeof (alg);
2374 		i++;
2375 	}
2376 
2377 	if (parms->idstr != NULL) {
2378 		KMF_DATA iddata = { NULL, 0 };
2379 
2380 		/*
2381 		 * ID String parameter is assumed to be of form:
2382 		 * XX:XX:XX:XX:XX ... :XX
2383 		 * where XX is a hex number.
2384 		 *
2385 		 * We must convert this back to binary in order to
2386 		 * use it in a search.
2387 		 */
2388 		rv = IDStringToData(parms->idstr, &iddata);
2389 		if (rv == KMF_OK) {
2390 			pTmpl[i].type = CKA_ID;
2391 			pTmpl[i].pValue = iddata.Data;
2392 			pTmpl[i].ulValueLen = iddata.Length;
2393 			i++;
2394 		} else {
2395 			return (rv);
2396 		}
2397 	}
2398 
2399 	if (parms->pkcs11parms.private) {
2400 		pTmpl[i].type = CKA_PRIVATE;
2401 		pTmpl[i].pValue = &true;
2402 		pTmpl[i].ulValueLen = sizeof (true);
2403 		i++;
2404 	}
2405 
2406 	if (is_token) {
2407 		rv = pk11_authenticate(handle, &parms->cred);
2408 		if (rv != KMF_OK) {
2409 			return (rv);
2410 		}
2411 	}
2412 
2413 	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2414 	if (ckrv == CKR_OK) {
2415 		CK_ULONG obj_count, n = 0;
2416 		while (ckrv == CKR_OK && n < want_keys) {
2417 			CK_OBJECT_HANDLE hObj;
2418 
2419 			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2420 				1, &obj_count);
2421 			if (ckrv == CKR_OK && obj_count == 1) {
2422 				if (keys != NULL) {
2423 					CK_ULONG keytype;
2424 					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2425 					keys[n].keyclass = parms->keyclass;
2426 					keys[n].israw = FALSE;
2427 					keys[n].keyp = (void *)hObj;
2428 
2429 					ckrv = getObjectKeytype(handle,
2430 						(CK_OBJECT_HANDLE)keys[n].keyp,
2431 						&keytype);
2432 					if (ckrv != CKR_OK)
2433 						goto end;
2434 
2435 					ckrv = getObjectLabel(handle,
2436 						(CK_OBJECT_HANDLE)keys[n].keyp,
2437 						&(keys[n].keylabel));
2438 					if (ckrv != CKR_OK)
2439 						goto end;
2440 
2441 					if (keytype == CKK_RSA)
2442 						keys[n].keyalg = KMF_RSA;
2443 					else if (keytype == CKK_DSA)
2444 						keys[n].keyalg = KMF_DSA;
2445 					else if (keytype == CKK_AES)
2446 						keys[n].keyalg = KMF_AES;
2447 					else if (keytype == CKK_RC4)
2448 						keys[n].keyalg = KMF_RC4;
2449 					else if (keytype == CKK_DES)
2450 						keys[n].keyalg = KMF_DES;
2451 					else if (keytype == CKK_DES3)
2452 						keys[n].keyalg = KMF_DES3;
2453 
2454 				}
2455 				n++;
2456 			} else {
2457 				break;
2458 			}
2459 		}
2460 		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2461 
2462 		/* "numkeys" indicates the number that were actually found */
2463 		*numkeys = n;
2464 	}
2465 	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0 &&
2466 		parms->format == KMF_FORMAT_RAWKEY) {
2467 		/* Convert keys to "rawkey" format */
2468 		for (i = 0; i < (*numkeys); i++) {
2469 			KMF_RAW_KEY_DATA *rkey = NULL;
2470 			rv = keyObj2RawKey(handle, &keys[i], &rkey);
2471 			if (rv == KMF_OK) {
2472 				keys[i].keyp = rkey;
2473 				keys[i].israw = TRUE;
2474 			} else {
2475 				break;
2476 			}
2477 		}
2478 	}
2479 end:
2480 	if (ckrv != CKR_OK) {
2481 		SET_ERROR(kmfh, ckrv);
2482 		/* Report authentication failures to the caller */
2483 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2484 		    ckrv == CKR_PIN_INCORRECT ||
2485 		    ckrv == CKR_PIN_INVALID ||
2486 		    ckrv == CKR_PIN_EXPIRED ||
2487 		    ckrv == CKR_PIN_LOCKED ||
2488 		    ckrv == CKR_SESSION_READ_ONLY)
2489 			rv = KMF_ERR_AUTH_FAILED;
2490 		else
2491 			rv = KMF_ERR_INTERNAL;
2492 	} else if ((*numkeys) == 0) {
2493 		rv = KMF_ERR_KEY_NOT_FOUND;
2494 	}
2495 
2496 	return (rv);
2497 }
2498 
2499 static char *
2500 convertDate(char *fulldate)
2501 {
2502 	struct tm tms;
2503 	char newtime[9];
2504 
2505 	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2506 
2507 	if (tms.tm_year < 69)
2508 		tms.tm_year += 100;
2509 
2510 	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2511 
2512 	newtime[8] = 0;
2513 
2514 	/* memory returned must be freed by the caller */
2515 	return ((char *)strdup(newtime));
2516 }
2517 
2518 KMF_RETURN
2519 KMFPK11_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2520 	KMF_RAW_KEY_DATA *rawkey)
2521 {
2522 	KMF_RETURN rv = KMF_OK;
2523 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2524 	int i;
2525 	CK_RV		ckrv = CKR_OK;
2526 	CK_ATTRIBUTE	templ[32];
2527 	CK_OBJECT_HANDLE keyobj;
2528 	CK_KEY_TYPE	keytype;
2529 	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2530 	CK_BBOOL	cktrue = TRUE;
2531 	CK_DATE		startdate, enddate;
2532 	KMF_DATA	id = {NULL, 0};
2533 	KMF_DATA	subject = {NULL, 0};
2534 	KMF_X509EXT_KEY_USAGE kuext;
2535 	KMF_X509_CERTIFICATE *x509 = NULL;
2536 	CK_BBOOL	kufound;
2537 	char		*notbefore = NULL, *start = NULL;
2538 	char		*notafter = NULL, *end = NULL;
2539 
2540 	if (!kmfh)
2541 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2542 
2543 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2544 		return (KMF_ERR_NO_TOKEN_SELECTED);
2545 
2546 	if (params == NULL || params->certificate == NULL ||
2547 		rawkey == NULL)
2548 		return (KMF_ERR_BAD_PARAMETER);
2549 
2550 	if (rawkey->keytype == KMF_RSA)
2551 		keytype = CKK_RSA;
2552 	else if (rawkey->keytype == KMF_DSA)
2553 		keytype = CKK_DSA;
2554 	else
2555 		return (KMF_ERR_BAD_PARAMETER);
2556 
2557 	rv = pk11_authenticate(handle, &params->cred);
2558 	if (rv != KMF_OK) {
2559 		return (rv);
2560 	}
2561 
2562 	id.Data = NULL;
2563 	id.Length = 0;
2564 	rv = KMF_GetCertIDData(params->certificate, &id);
2565 	if (rv != KMF_OK) {
2566 		goto cleanup;
2567 	}
2568 
2569 	rv = DerDecodeSignedCertificate(
2570 		(const KMF_DATA *)params->certificate, &x509);
2571 	if (rv != KMF_OK) {
2572 		goto cleanup;
2573 	}
2574 
2575 	rv = DerEncodeName(&x509->certificate.subject, &subject);
2576 	if (rv != KMF_OK) {
2577 		goto cleanup;
2578 	}
2579 
2580 	rv = KMF_GetCertStartDateString(handle, params->certificate,
2581 		&notbefore);
2582 	if (rv != KMF_OK) {
2583 		goto cleanup;
2584 	}
2585 	start = convertDate(notbefore);
2586 
2587 	rv = KMF_GetCertEndDateString(handle, params->certificate,
2588 		&notafter);
2589 	if (rv != KMF_OK) {
2590 		goto cleanup;
2591 	}
2592 	end = convertDate(notafter);
2593 
2594 	if ((rv = KMF_GetCertKeyUsageExt(params->certificate, &kuext))
2595 		!= KMF_OK && rv != KMF_ERR_EXTENSION_NOT_FOUND)
2596 		goto cleanup;
2597 
2598 	kufound = (rv == KMF_OK);
2599 	rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND above */
2600 
2601 	i = 0;
2602 	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2603 	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2604 	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2605 	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2606 	SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++;
2607 
2608 	/*
2609 	 * Only set the KeyUsage stuff if the KU extension was present.
2610 	 */
2611 	if (kufound) {
2612 		CK_BBOOL	condition;
2613 
2614 		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
2615 			B_TRUE : B_FALSE;
2616 		SETATTR(templ, i, CKA_UNWRAP, &condition,
2617 			sizeof (CK_BBOOL)); i++;
2618 		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
2619 			B_TRUE : B_FALSE;
2620 		SETATTR(templ, i, CKA_DECRYPT, &condition,
2621 			sizeof (CK_BBOOL)); i++;
2622 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2623 			B_TRUE : B_FALSE;
2624 		SETATTR(templ, i, CKA_SIGN, &condition,
2625 			sizeof (CK_BBOOL)); i++;
2626 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2627 			B_TRUE : B_FALSE;
2628 		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
2629 			sizeof (CK_BBOOL)); i++;
2630 	}
2631 	if (params->label != NULL) {
2632 		SETATTR(templ, i, CKA_LABEL, params->label,
2633 			strlen(params->label));
2634 		i++;
2635 	}
2636 	if (id.Data != NULL &&
2637 		id.Data != NULL && id.Length > 0) {
2638 		SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2639 		i++;
2640 	}
2641 	if (start != NULL) {
2642 		/*
2643 		 * This make some potentially dangerous assumptions:
2644 		 *  1. that the startdate in the parameter block is
2645 		 * properly formatted as YYYYMMDD
2646 		 *  2. That the CK_DATE structure is always the same.
2647 		 */
2648 		(void) memcpy(&startdate, start, sizeof (CK_DATE));
2649 		SETATTR(templ, i, CKA_START_DATE, &startdate,
2650 			sizeof (startdate));
2651 		i++;
2652 	}
2653 	if (end != NULL) {
2654 		(void) memcpy(&enddate, end, sizeof (CK_DATE));
2655 		SETATTR(templ, i, CKA_END_DATE, &enddate, sizeof (enddate));
2656 		i++;
2657 	}
2658 	if (keytype == CKK_RSA) {
2659 		SETATTR(templ, i, CKA_MODULUS,
2660 			rawkey->rawdata.rsa.mod.val,
2661 			rawkey->rawdata.rsa.mod.len);
2662 		i++;
2663 		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
2664 			rawkey->rawdata.rsa.pubexp.val,
2665 			rawkey->rawdata.rsa.pubexp.len);
2666 		i++;
2667 		if (rawkey->rawdata.rsa.priexp.val != NULL) {
2668 			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
2669 				rawkey->rawdata.rsa.priexp.val,
2670 				rawkey->rawdata.rsa.priexp.len);
2671 			i++;
2672 		}
2673 		if (rawkey->rawdata.rsa.prime1.val != NULL) {
2674 			SETATTR(templ, i, CKA_PRIME_1,
2675 				rawkey->rawdata.rsa.prime1.val,
2676 				rawkey->rawdata.rsa.prime1.len);
2677 			i++;
2678 		}
2679 		if (rawkey->rawdata.rsa.prime2.val != NULL) {
2680 			SETATTR(templ, i, CKA_PRIME_2,
2681 				rawkey->rawdata.rsa.prime2.val,
2682 				rawkey->rawdata.rsa.prime2.len);
2683 			i++;
2684 		}
2685 		if (rawkey->rawdata.rsa.exp1.val != NULL) {
2686 			SETATTR(templ, i, CKA_EXPONENT_1,
2687 				rawkey->rawdata.rsa.exp1.val,
2688 				rawkey->rawdata.rsa.exp1.len);
2689 			i++;
2690 		}
2691 		if (rawkey->rawdata.rsa.exp2.val != NULL) {
2692 			SETATTR(templ, i, CKA_EXPONENT_2,
2693 				rawkey->rawdata.rsa.exp2.val,
2694 				rawkey->rawdata.rsa.exp2.len);
2695 			i++;
2696 		}
2697 		if (rawkey->rawdata.rsa.coef.val != NULL) {
2698 			SETATTR(templ, i, CKA_COEFFICIENT,
2699 				rawkey->rawdata.rsa.coef.val,
2700 				rawkey->rawdata.rsa.coef.len);
2701 			i++;
2702 		}
2703 	} else {
2704 		SETATTR(templ, i, CKA_PRIME,
2705 			rawkey->rawdata.dsa.prime.val,
2706 			rawkey->rawdata.dsa.prime.len);
2707 		i++;
2708 		SETATTR(templ, i, CKA_SUBPRIME,
2709 			rawkey->rawdata.dsa.subprime.val,
2710 			rawkey->rawdata.dsa.subprime.len);
2711 		i++;
2712 		SETATTR(templ, i, CKA_BASE,
2713 			rawkey->rawdata.dsa.base.val,
2714 			rawkey->rawdata.dsa.base.len);
2715 		i++;
2716 		SETATTR(templ, i, CKA_VALUE,
2717 			rawkey->rawdata.dsa.value.val,
2718 			rawkey->rawdata.dsa.value.len);
2719 		i++;
2720 	}
2721 
2722 	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
2723 	if (ckrv != CKR_OK) {
2724 		SET_ERROR(kmfh, ckrv);
2725 
2726 		/* Report authentication failures to the caller */
2727 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2728 		    ckrv == CKR_PIN_INCORRECT ||
2729 		    ckrv == CKR_PIN_INVALID ||
2730 		    ckrv == CKR_PIN_EXPIRED ||
2731 		    ckrv == CKR_PIN_LOCKED ||
2732 		    ckrv == CKR_SESSION_READ_ONLY)
2733 			rv = KMF_ERR_AUTH_FAILED;
2734 		else
2735 			rv = KMF_ERR_INTERNAL;
2736 	}
2737 cleanup:
2738 	KMF_FreeData(&id);
2739 	KMF_FreeData(&subject);
2740 	KMF_FreeSignedCert(x509);
2741 	free(x509);
2742 
2743 	return (rv);
2744 }
2745 
2746 KMF_RETURN
2747 KMFPK11_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
2748 	KMF_KEY_HANDLE *symkey)
2749 {
2750 	KMF_RETURN		rv = KMF_OK;
2751 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2752 	CK_RV			ckrv;
2753 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2754 	CK_OBJECT_HANDLE	keyhandle;
2755 	CK_MECHANISM		keyGenMech;
2756 	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
2757 	CK_ULONG		secKeyType;
2758 	CK_ULONG		secKeyLen;	/* for RC4 and AES */
2759 	CK_BBOOL		true = TRUE;
2760 	CK_BBOOL		false = FALSE;
2761 	CK_ATTRIBUTE		templ[15];
2762 	int i;
2763 
2764 	if (kmfh == NULL)
2765 		return (KMF_ERR_UNINITIALIZED);
2766 
2767 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2768 		return (KMF_ERR_NO_TOKEN_SELECTED);
2769 
2770 	if (params == NULL)
2771 		return (KMF_ERR_BAD_PARAMETER);
2772 
2773 	keyGenMech.pParameter = NULL_PTR;
2774 	keyGenMech.ulParameterLen = 0;
2775 	switch (params->keytype) {
2776 	case KMF_AES:
2777 		keyGenMech.mechanism = CKM_AES_KEY_GEN;
2778 		secKeyType = CKK_AES;
2779 		break;
2780 	case KMF_RC4:
2781 		keyGenMech.mechanism = CKM_RC4_KEY_GEN;
2782 		secKeyType = CKK_RC4;
2783 		break;
2784 	case KMF_DES:
2785 		keyGenMech.mechanism = CKM_DES_KEY_GEN;
2786 		secKeyType = CKK_DES;
2787 		break;
2788 	case KMF_DES3:
2789 		keyGenMech.mechanism = CKM_DES3_KEY_GEN;
2790 		secKeyType = CKK_DES3;
2791 		break;
2792 	default:
2793 		return (KMF_ERR_BAD_KEY_TYPE);
2794 	}
2795 
2796 	i = 0;
2797 	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2798 	i++;
2799 	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2800 	i++;
2801 
2802 	if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
2803 		if ((params->keylength % 8) != 0) {
2804 			return (KMF_ERR_BAD_KEY_SIZE);
2805 		}
2806 		secKeyLen = params->keylength/8;  /* in bytes for RC4/AES */
2807 		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
2808 		    sizeof (secKeyLen));
2809 		i++;
2810 	}
2811 
2812 	if (params->keylabel != NULL) {
2813 		SETATTR(templ, i, CKA_LABEL, params->keylabel,
2814 		    strlen(params->keylabel));
2815 		i++;
2816 	}
2817 
2818 	if (params->pkcs11parms.sensitive == B_TRUE) {
2819 		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2820 	} else {
2821 		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2822 	}
2823 	i++;
2824 
2825 	if (params->pkcs11parms.not_extractable == B_TRUE) {
2826 		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2827 	} else {
2828 		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2829 	}
2830 	i++;
2831 
2832 	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2833 	i++;
2834 	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2835 	i++;
2836 	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
2837 	i++;
2838 	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
2839 	i++;
2840 	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2841 	i++;
2842 	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
2843 	i++;
2844 
2845 	rv = pk11_authenticate(handle, &params->cred);
2846 	if (rv != KMF_OK) {
2847 		return (rv);
2848 	}
2849 
2850 	ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i, &keyhandle);
2851 	if (ckrv != CKR_OK) {
2852 		SET_ERROR(kmfh, ckrv);
2853 		rv = KMF_ERR_KEYGEN_FAILED;
2854 		goto out;
2855 	}
2856 
2857 	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2858 	symkey->keyalg = params->keytype;
2859 	symkey->keyclass = KMF_SYMMETRIC;
2860 	symkey->israw = FALSE;
2861 	symkey->keyp = (void *)keyhandle;
2862 
2863 out:
2864 	return (rv);
2865 }
2866 
2867 
2868 KMF_RETURN
2869 KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2870     KMF_RAW_SYM_KEY *rkey)
2871 {
2872 	KMF_RETURN		rv = KMF_OK;
2873 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2874 
2875 	if (kmfh == NULL)
2876 		return (KMF_ERR_UNINITIALIZED);
2877 
2878 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2879 		return (KMF_ERR_NO_TOKEN_SELECTED);
2880 
2881 	if (symkey == NULL || rkey == NULL)
2882 		return (KMF_ERR_BAD_PARAMETER);
2883 	else if (symkey->keyclass != KMF_SYMMETRIC)
2884 		return (KMF_ERR_BAD_KEY_CLASS);
2885 
2886 	if (symkey->israw) {
2887 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2888 
2889 		if (rawkey == NULL ||
2890 		    rawkey->rawdata.sym.keydata.val == NULL ||
2891 		    rawkey->rawdata.sym.keydata.len == 0)
2892 			return (KMF_ERR_BAD_KEYHANDLE);
2893 
2894 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2895 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2896 			return (KMF_ERR_MEMORY);
2897 		(void) memcpy(rkey->keydata.val,
2898 			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2899 	} else {
2900 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
2901 	}
2902 
2903 	return (rv);
2904 }
2905 
2906 KMF_RETURN
2907 KMFPK11_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2908 	KMF_CREDENTIAL *newpin)
2909 {
2910 	KMF_RETURN	ret = KMF_OK;
2911 	CK_RV		rv = CKR_OK;
2912 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
2913 	CK_SESSION_HANDLE	session = NULL;
2914 
2915 	if (handle == NULL || params == NULL || newpin == NULL)
2916 		return (KMF_ERR_BAD_PARAMETER);
2917 
2918 	rv = C_OpenSession(params->pkcs11parms.slot,
2919 		CKF_SERIAL_SESSION | CKF_RW_SESSION,
2920 		NULL, NULL, &session);
2921 	if (rv != CKR_OK) {
2922 		SET_ERROR(kmfh, rv);
2923 		ret = KMF_ERR_UNINITIALIZED;
2924 		goto end;
2925 	}
2926 
2927 	rv = C_SetPIN(session,
2928 		(CK_BYTE *)params->cred.cred, params->cred.credlen,
2929 		(CK_BYTE *)newpin->cred, newpin->credlen);
2930 
2931 	if (rv != CKR_OK) {
2932 		SET_ERROR(kmfh, rv);
2933 		if (rv == CKR_PIN_INCORRECT ||
2934 		    rv == CKR_PIN_INVALID ||
2935 		    rv == CKR_PIN_EXPIRED ||
2936 		    rv == CKR_PIN_LOCKED)
2937 			ret = KMF_ERR_AUTH_FAILED;
2938 		else
2939 			ret = KMF_ERR_INTERNAL;
2940 	}
2941 end:
2942 	if (session != NULL)
2943 		(void) C_CloseSession(session);
2944 	return (ret);
2945 }
2946