xref: /illumos-gate/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c (revision 150d2c5288c645a1c1a7d2bee61199a3729406c7)
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 <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 CK_RV
61 getObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
62 
63 static KMF_RETURN
64 keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
65 
66 KMF_RETURN
67 KMFPK11_ConfigureKeystore(KMF_HANDLE_T, KMF_CONFIG_PARAMS *);
68 
69 KMF_RETURN
70 KMFPK11_FindCert(KMF_HANDLE_T,
71 	KMF_FINDCERT_PARAMS *,
72 	KMF_X509_DER_CERT *,
73 	uint32_t *);
74 
75 void
76 KMFPK11_FreeKMFCert(KMF_HANDLE_T,
77 	KMF_X509_DER_CERT *kmf_cert);
78 
79 KMF_RETURN
80 KMFPK11_StoreCert(KMF_HANDLE_T, KMF_STORECERT_PARAMS *, KMF_DATA *);
81 
82 KMF_RETURN
83 KMFPK11_ImportCert(KMF_HANDLE_T, KMF_IMPORTCERT_PARAMS *);
84 
85 KMF_RETURN
86 KMFPK11_DeleteCert(KMF_HANDLE_T, KMF_DELETECERT_PARAMS *);
87 
88 KMF_RETURN
89 KMFPK11_CreateKeypair(KMF_HANDLE_T, KMF_CREATEKEYPAIR_PARAMS *,
90 	KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
91 
92 KMF_RETURN
93 KMFPK11_DeleteKey(KMF_HANDLE_T, KMF_DELETEKEY_PARAMS *,
94 	KMF_KEY_HANDLE *, boolean_t);
95 
96 KMF_RETURN
97 KMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
98 
99 KMF_RETURN
100 KMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
101 	KMF_DATA *, KMF_DATA *);
102 
103 KMF_RETURN
104 KMFPK11_GetErrorString(KMF_HANDLE_T, char **);
105 
106 KMF_RETURN
107 KMFPK11_GetPrikeyByCert(KMF_HANDLE_T, KMF_CRYPTOWITHCERT_PARAMS *, KMF_DATA *,
108 	KMF_KEY_HANDLE *, KMF_KEY_ALG);
109 
110 KMF_RETURN
111 KMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
112 	KMF_DATA *, KMF_DATA *);
113 
114 KMF_RETURN
115 KMFPK11_FindKey(KMF_HANDLE_T, KMF_FINDKEY_PARAMS *,
116 	KMF_KEY_HANDLE *, uint32_t *);
117 
118 KMF_RETURN
119 KMFPK11_StorePrivateKey(KMF_HANDLE_T, KMF_STOREKEY_PARAMS *,
120 	KMF_RAW_KEY_DATA *);
121 
122 KMF_RETURN
123 KMFPK11_CreateSymKey(KMF_HANDLE_T, KMF_CREATESYMKEY_PARAMS *,
124 	KMF_KEY_HANDLE *);
125 
126 KMF_RETURN
127 KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
128 
129 KMF_RETURN
130 KMFPK11_SetTokenPin(KMF_HANDLE_T, KMF_SETPIN_PARAMS *, KMF_CREDENTIAL *);
131 
132 static
133 KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
134 {
135 	1,			/* Version */
136 	KMFPK11_ConfigureKeystore,
137 	KMFPK11_FindCert,
138 	KMFPK11_FreeKMFCert,
139 	KMFPK11_StoreCert,
140 	KMFPK11_ImportCert,
141 	NULL,			/* ImportCRL */
142 	KMFPK11_DeleteCert,
143 	NULL,			/* DeleteCRL */
144 	KMFPK11_CreateKeypair,
145 	KMFPK11_FindKey,
146 	KMFPK11_EncodePubKeyData,
147 	KMFPK11_SignData,
148 	KMFPK11_DeleteKey,
149 	NULL,			/* ListCRL */
150 	NULL,			/* FindCRL */
151 	NULL,			/* FindCertInCRL */
152 	KMFPK11_GetErrorString,
153 	KMFPK11_GetPrikeyByCert,
154 	KMFPK11_DecryptData,
155 	NULL,			/* ExportP12 */
156 	KMFPK11_StorePrivateKey,
157 	KMFPK11_CreateSymKey,
158 	KMFPK11_GetSymKeyValue,
159 	KMFPK11_SetTokenPin,
160 	NULL			/* Finalize */
161 };
162 
163 KMF_PLUGIN_FUNCLIST *
164 KMF_Plugin_Initialize()
165 {
166 	return (&pk11token_plugin_table);
167 }
168 
169 KMF_RETURN
170 KMFPK11_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
171 {
172 	KMF_RETURN rv = KMF_OK;
173 
174 	if (params == NULL || params->pkcs11config.label == NULL)
175 		return (KMF_ERR_BAD_PARAMETER);
176 
177 	rv = KMF_SelectToken(handle, params->pkcs11config.label,
178 	    params->pkcs11config.readonly);
179 
180 	return (rv);
181 }
182 
183 static KMF_RETURN
184 pk11_authenticate(KMF_HANDLE_T handle,
185 	KMF_CREDENTIAL *cred)
186 {
187 
188 	CK_RV ck_rv = CKR_OK;
189 	CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
190 
191 	if (hSession == NULL)
192 		return (KMF_ERR_NO_TOKEN_SELECTED);
193 
194 	if (cred == NULL || cred->cred == NULL || cred->credlen == 0) {
195 		return (KMF_ERR_BAD_PARAMETER);
196 	}
197 
198 	if ((ck_rv = C_Login(hSession, CKU_USER,
199 		(uchar_t *)cred->cred, cred->credlen)) != CKR_OK) {
200 		if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
201 			handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
202 			handle->lasterr.errcode = ck_rv;
203 			return (KMF_ERR_AUTH_FAILED);
204 		}
205 	}
206 
207 	return (KMF_OK);
208 }
209 
210 static KMF_RETURN
211 PK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
212 		KMF_X509_DER_CERT *kmfcert)
213 {
214 	KMF_RETURN rv = 0;
215 	CK_RV ckrv = CKR_OK;
216 
217 	CK_CERTIFICATE_TYPE cktype;
218 	CK_OBJECT_CLASS	class;
219 	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
220 	CK_BYTE *subject = NULL, *value = NULL;
221 	char *label = NULL;
222 	CK_ATTRIBUTE templ[10];
223 
224 	(void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
225 	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
226 
227 	/*  Is this a certificate object ? */
228 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
229 	if (ckrv != CKR_OK || class != CKO_CERTIFICATE)  {
230 		SET_ERROR(kmfh, ckrv);
231 		return (KMF_ERR_INTERNAL);
232 	}
233 
234 	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
235 	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
236 
237 	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
238 		SET_ERROR(kmfh, ckrv);
239 		return (ckrv);
240 	} else {
241 		int i = 0;
242 		/* What attributes are available and how big are they? */
243 		subject_len = issuer_len = serno_len = id_len = value_len = 0;
244 
245 		SETATTR(templ, i, CKA_SUBJECT,	NULL, subject_len);
246 		i++;
247 		SETATTR(templ, i, CKA_ISSUER,	NULL, issuer_len);
248 		i++;
249 		SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
250 		i++;
251 		SETATTR(templ, i, CKA_ID, NULL, id_len);
252 		i++;
253 		SETATTR(templ, i, CKA_VALUE, NULL, value_len);
254 		i++;
255 
256 		/*
257 		 * Query the object with NULL values in the pValue spot
258 		 * so we know how much space to allocate for each field.
259 		 */
260 		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
261 		if (ckrv != CKR_OK)  {
262 			SET_ERROR(kmfh, ckrv);
263 			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
264 		}
265 
266 		subject_len	= templ[0].ulValueLen;
267 		issuer_len	= templ[1].ulValueLen;
268 		serno_len	= templ[2].ulValueLen;
269 		id_len		= templ[3].ulValueLen;
270 		value_len	= templ[4].ulValueLen;
271 
272 		/*
273 		 * For PKCS#11 CKC_X_509 certificate objects,
274 		 * the following attributes must be defined.
275 		 * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
276 		 * CKA_VALUE.
277 		 */
278 		if (subject_len == 0 || issuer_len == 0 ||
279 		    serno_len == 0 || value_len == 0) {
280 			return (KMF_ERR_INTERNAL);
281 		}
282 
283 		/* Only fetch the value field if we are saving the data */
284 		if (kmfcert != NULL) {
285 			int i = 0;
286 			value = malloc(value_len);
287 			if (value == NULL) {
288 				rv = KMF_ERR_MEMORY;
289 				goto errout;
290 			}
291 
292 			SETATTR(templ, i, CKA_VALUE, value, value_len);
293 			i++;
294 
295 			/* re-query the object with room for the value attr */
296 			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
297 				templ, i);
298 
299 			if (ckrv != CKR_OK)  {
300 				SET_ERROR(kmfh, ckrv);
301 				rv = KMF_ERR_INTERNAL;
302 				goto errout;
303 			}
304 
305 			kmfcert->certificate.Data = value;
306 			kmfcert->certificate.Length = value_len;
307 			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
308 			kmfcert->kmf_private.keystore_type =
309 				KMF_KEYSTORE_PK11TOKEN;
310 
311 			ckrv = getObjectLabel(kmfh, hObj, &label);
312 			if (ckrv == CKR_OK && label != NULL) {
313 				kmfcert->kmf_private.label = (char *)label;
314 			}
315 
316 			rv = KMF_OK;
317 		}
318 	}
319 
320 errout:
321 	if (rv != KMF_OK) {
322 		if (subject)
323 			free(subject);
324 		if (value)
325 			free(value);
326 
327 		if (kmfcert) {
328 			kmfcert->certificate.Data = NULL;
329 			kmfcert->certificate.Length = 0;
330 		}
331 	}
332 	return (rv);
333 }
334 
335 static void
336 free_objlist(OBJLIST *head)
337 {
338 	OBJLIST *temp = head;
339 
340 	while (temp != NULL) {
341 		head = head->next;
342 		free(temp);
343 		temp = head;
344 	}
345 }
346 
347 /*
348  * The caller should make sure that the templ->pValue is NULL since
349  * it will be overwritten below.
350  */
351 static KMF_RETURN
352 get_attr(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
353 	CK_ATTRIBUTE *templ)
354 {
355 	CK_RV rv;
356 
357 	rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
358 	if (rv != CKR_OK) {
359 		SET_ERROR(kmfh, rv);
360 		return (KMF_ERR_INTERNAL);
361 	}
362 
363 	if (templ->ulValueLen > 0) {
364 		templ->pValue = malloc(templ->ulValueLen);
365 		if (templ->pValue == NULL)
366 			return (KMF_ERR_MEMORY);
367 
368 		rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
369 		if (rv != CKR_OK) {
370 			SET_ERROR(kmfh, rv);
371 			return (KMF_ERR_INTERNAL);
372 		}
373 	}
374 
375 	return (KMF_OK);
376 }
377 
378 /*
379  * Match a certificate with an issuer and/or subject name.
380  * This is tricky because we cannot reliably compare DER encodings
381  * because RDNs may have their AV-pairs in different orders even
382  * if the values are the same.  You must compare individual
383  * AV pairs for the RDNs.
384  *
385  * RETURN: 0 for a match, non-zero for a non-match.
386  */
387 static KMF_RETURN
388 matchcert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
389 	KMF_X509_NAME *issuer, KMF_X509_NAME *subject)
390 {
391 	KMF_RETURN rv = KMF_OK;
392 	CK_ATTRIBUTE certattr;
393 	KMF_DATA name;
394 	KMF_X509_NAME dn;
395 
396 	if (issuer->numberOfRDNs > 0) {
397 		certattr.type = CKA_ISSUER;
398 		certattr.pValue = NULL;
399 		certattr.ulValueLen = 0;
400 
401 		rv = get_attr(kmfh, obj, &certattr);
402 
403 		if (rv == KMF_OK) {
404 			name.Data = certattr.pValue;
405 			name.Length = certattr.ulValueLen;
406 			rv = DerDecodeName(&name, &dn);
407 			if (rv == KMF_OK) {
408 				rv = KMF_CompareRDNs(issuer, &dn);
409 				KMF_FreeDN(&dn);
410 			}
411 			free(certattr.pValue);
412 		}
413 
414 		if (rv != KMF_OK)
415 			return (rv);
416 	}
417 	if (subject->numberOfRDNs > 0) {
418 		certattr.type = CKA_SUBJECT;
419 		certattr.pValue = NULL;
420 		certattr.ulValueLen = 0;
421 
422 		rv = get_attr(kmfh, obj, &certattr);
423 
424 		if (rv == KMF_OK) {
425 			name.Data = certattr.pValue;
426 			name.Length = certattr.ulValueLen;
427 			rv = DerDecodeName(&name, &dn);
428 			if (rv == KMF_OK) {
429 				rv = KMF_CompareRDNs(subject, &dn);
430 				KMF_FreeDN(&dn);
431 			}
432 			free(certattr.pValue);
433 		}
434 	}
435 
436 	return (rv);
437 }
438 
439 /*
440  * delete "curr" node from the "newlist".
441  */
442 static void
443 pk11_delete_obj_from_list(OBJLIST **newlist,
444 	OBJLIST **prev, OBJLIST **curr)
445 {
446 
447 	if (*curr == *newlist) {
448 		/* first node in the list */
449 		*newlist = (*curr)->next;
450 		*prev = (*curr)->next;
451 		free(*curr);
452 		*curr = *newlist;
453 	} else {
454 		(*prev)->next = (*curr)->next;
455 		free(*curr);
456 		*curr = (*prev)->next;
457 	}
458 }
459 
460 /*
461  * prepare_object_search
462  *
463  * Because this code is shared by the FindCert and
464  * DeleteCert functions, put it in a separate routine
465  * to save some work and make code easier to debug and
466  * read.
467  */
468 static KMF_RETURN
469 search_certs(KMF_HANDLE_T handle,
470 	char *label, char *issuer, char *subject, KMF_BIGINT *serial,
471 	boolean_t private, KMF_CERT_VALIDITY validity,
472 	OBJLIST **objlist, uint32_t *numobj)
473 {
474 	KMF_RETURN rv = KMF_OK;
475 	CK_RV ckrv = CKR_OK;
476 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
477 	CK_ATTRIBUTE templ[10];
478 	CK_BBOOL true = TRUE;
479 	CK_OBJECT_CLASS	oclass = CKO_CERTIFICATE;
480 	CK_CERTIFICATE_TYPE ctype = CKC_X_509;
481 	KMF_X509_NAME subjectDN, issuerDN;
482 	int i;
483 	OBJLIST *newlist, *tail;
484 	CK_ULONG num = 0;
485 	uint32_t num_ok_certs = 0; /* number of non-expired or expired certs */
486 
487 	(void) memset(&templ, 0, 10 * sizeof (CK_ATTRIBUTE));
488 	(void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
489 	(void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
490 	i = 0;
491 	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
492 	SETATTR(templ, i, CKA_CLASS, &oclass, sizeof (oclass)); i++;
493 	SETATTR(templ, i, CKA_CERTIFICATE_TYPE, &ctype,
494 		sizeof (ctype)); i++;
495 
496 	if (label != NULL && strlen(label)) {
497 		SETATTR(templ, i, CKA_LABEL, label, strlen(label));
498 		i++;
499 	}
500 	if (private) {
501 		SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true)); i++;
502 	}
503 
504 	if (issuer != NULL && strlen(issuer)) {
505 		if ((rv = KMF_DNParser(issuer, &issuerDN)) != KMF_OK)
506 			return (rv);
507 	}
508 	if (subject != NULL && strlen(subject)) {
509 		if ((rv = KMF_DNParser(subject, &subjectDN)) != KMF_OK)
510 			return (rv);
511 	}
512 
513 	if (serial != NULL && serial->val != NULL && serial->len > 0) {
514 		SETATTR(templ, i, CKA_SERIAL_NUMBER,
515 			serial->val, serial->len);
516 		i++;
517 	}
518 
519 	(*numobj) = 0;
520 	*objlist = NULL;
521 	newlist = NULL;
522 
523 	ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, i);
524 	if (ckrv != CKR_OK)
525 		goto cleanup;
526 
527 	tail = newlist = NULL;
528 	while (ckrv == CKR_OK) {
529 		CK_OBJECT_HANDLE tObj;
530 		ckrv = C_FindObjects(kmfh->pk11handle, &tObj, 1, &num);
531 		if (ckrv != CKR_OK || num == 0)
532 			break;
533 
534 		/*
535 		 * 'matchcert' returns 0 if subject/issuer match
536 		 *
537 		 * If no match, move on to the next one
538 		 */
539 		if (matchcert(kmfh, tObj, &issuerDN, &subjectDN))
540 			continue;
541 
542 		if (newlist == NULL) {
543 			newlist = malloc(sizeof (OBJLIST));
544 			if (newlist == NULL) {
545 				rv = KMF_ERR_MEMORY;
546 				break;
547 			}
548 			newlist->handle = tObj;
549 			newlist->next = NULL;
550 			tail = newlist;
551 		} else {
552 			tail->next = malloc(sizeof (OBJLIST));
553 			if (tail->next != NULL) {
554 				tail = tail->next;
555 			} else {
556 				rv = KMF_ERR_MEMORY;
557 				break;
558 			}
559 			tail->handle = tObj;
560 			tail->next = NULL;
561 		}
562 		(*numobj)++;
563 	}
564 	ckrv = C_FindObjectsFinal(kmfh->pk11handle);
565 
566 cleanup:
567 	if (ckrv != CKR_OK) {
568 		SET_ERROR(kmfh, ckrv);
569 		rv = KMF_ERR_INTERNAL;
570 		if (newlist != NULL) {
571 			free_objlist(newlist);
572 			*numobj = 0;
573 			newlist = NULL;
574 		}
575 	} else {
576 		if (validity == KMF_ALL_CERTS) {
577 			*objlist = newlist;
578 		} else {
579 			OBJLIST *node, *prev;
580 			KMF_X509_DER_CERT  tmp_kmf_cert;
581 			uint32_t i = 0;
582 
583 			node = prev = newlist;
584 			/*
585 			 * Now check to see if any found certificate is expired
586 			 * or valid.
587 			 */
588 			while (node != NULL && i < (*numobj)) {
589 				(void) memset(&tmp_kmf_cert, 0,
590 				    sizeof (KMF_X509_DER_CERT));
591 				rv = PK11Cert2KMFCert(kmfh, node->handle,
592 				    &tmp_kmf_cert);
593 				if (rv != KMF_OK) {
594 					goto cleanup1;
595 				}
596 
597 				rv = KMF_CheckCertDate(handle,
598 				    &tmp_kmf_cert.certificate);
599 
600 				if (validity == KMF_NONEXPIRED_CERTS) {
601 					if (rv == KMF_OK)  {
602 						num_ok_certs++;
603 						prev = node;
604 						node = node->next;
605 					} else if (rv ==
606 					    KMF_ERR_VALIDITY_PERIOD) {
607 						/*
608 						 * expired - remove it from list
609 						 */
610 						pk11_delete_obj_from_list(
611 						    &newlist, &prev, &node);
612 					} else {
613 						goto cleanup1;
614 					}
615 				}
616 
617 				if (validity == KMF_EXPIRED_CERTS) {
618 					if (rv == KMF_ERR_VALIDITY_PERIOD)  {
619 						num_ok_certs++;
620 						prev = node;
621 						node = node->next;
622 						rv = KMF_OK;
623 					} else if (rv == KMF_OK) {
624 						/*
625 						 * valid - remove it from list
626 						 */
627 						pk11_delete_obj_from_list(
628 						    &newlist, &prev, &node);
629 					} else {
630 						goto cleanup1;
631 					}
632 				}
633 				i++;
634 				KMF_FreeKMFCert(handle, &tmp_kmf_cert);
635 			}
636 			*numobj = num_ok_certs;
637 			*objlist = newlist;
638 		}
639 	}
640 
641 cleanup1:
642 	if (rv != KMF_OK && newlist != NULL) {
643 		free_objlist(newlist);
644 		*numobj = 0;
645 		*objlist = NULL;
646 	}
647 
648 	if (issuer != NULL)
649 		KMF_FreeDN(&issuerDN);
650 
651 	if (subject != NULL)
652 		KMF_FreeDN(&subjectDN);
653 
654 	return (rv);
655 }
656 
657 /*
658  * The caller may pass a NULL value for kmf_cert below and the function will
659  * just return the number of certs found (in num_certs).
660  */
661 KMF_RETURN
662 KMFPK11_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *params,
663 	KMF_X509_DER_CERT *kmf_cert,
664 	uint32_t *num_certs)
665 {
666 	KMF_RETURN rv = 0;
667 	uint32_t want_certs;
668 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
669 	OBJLIST *objlist = NULL;
670 
671 	if (!kmfh)
672 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
673 
674 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
675 		return (KMF_ERR_NO_TOKEN_SELECTED);
676 
677 	if (params == NULL || num_certs == NULL)
678 		return (KMF_ERR_BAD_PARAMETER);
679 
680 	if (*num_certs > 0)
681 		want_certs = *num_certs;
682 	else
683 		want_certs = MAXINT; /* count them all */
684 
685 	*num_certs = 0;
686 
687 	rv = search_certs(handle,
688 		params->certLabel, params->issuer,
689 		params->subject, params->serial,
690 		params->pkcs11parms.private,
691 		params->find_cert_validity,
692 		&objlist, num_certs);
693 
694 	if (rv == KMF_OK && objlist != NULL && kmf_cert != NULL) {
695 		OBJLIST *node = objlist;
696 		int i = 0;
697 		while (node != NULL && i < want_certs) {
698 			rv = PK11Cert2KMFCert(kmfh, node->handle,
699 				&kmf_cert[i]);
700 			i++;
701 			node = node->next;
702 		}
703 	}
704 
705 	if (objlist != NULL)
706 		free_objlist(objlist);
707 
708 	if (*num_certs == 0)
709 		rv = KMF_ERR_CERT_NOT_FOUND;
710 
711 	return (rv);
712 }
713 
714 /*ARGSUSED*/
715 void
716 KMFPK11_FreeKMFCert(KMF_HANDLE_T handle,
717 	KMF_X509_DER_CERT *kmf_cert)
718 {
719 	if (kmf_cert != NULL && kmf_cert->certificate.Data != NULL) {
720 		free(kmf_cert->certificate.Data);
721 		kmf_cert->certificate.Data = NULL;
722 		kmf_cert->certificate.Length = 0;
723 
724 		if (kmf_cert->kmf_private.label != NULL) {
725 			free(kmf_cert->kmf_private.label);
726 			kmf_cert->kmf_private.label = NULL;
727 		}
728 	}
729 }
730 
731 KMF_RETURN
732 KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
733 		KMF_DATA *eData)
734 {
735 	KMF_RETURN ret = KMF_OK;
736 	CK_RV rv;
737 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
738 	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
739 	CK_KEY_TYPE ckKeyType;
740 	KMF_DATA Modulus, Exponent, Prime, Subprime, Base, Value;
741 	KMF_OID *Algorithm;
742 	BerElement *asn1 = NULL;
743 	BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
744 	KMF_X509_SPKI spki;
745 
746 	CK_ATTRIBUTE rsaTemplate[4];
747 	CK_ATTRIBUTE dsaTemplate[6];
748 
749 	if (!kmfh)
750 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
751 
752 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
753 		return (KMF_ERR_NO_TOKEN_SELECTED);
754 
755 	if (pKey == NULL || pKey->keyp == CK_INVALID_HANDLE)
756 		return (KMF_ERR_BAD_PARAMETER);
757 
758 	(void) memset(&Modulus, 0, sizeof (Modulus));
759 	(void) memset(&Exponent, 0, sizeof (Exponent));
760 	(void) memset(&Prime, 0, sizeof (Prime));
761 	(void) memset(&Subprime, 0, sizeof (Subprime));
762 	(void) memset(&Base, 0, sizeof (Base));
763 	(void) memset(&Value, 0, sizeof (Value));
764 
765 	SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
766 	SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
767 	SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, &Modulus.Length);
768 	SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, Exponent.Data,
769 		&Exponent.Length);
770 
771 	SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
772 	SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
773 	SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, &Prime.Length);
774 	SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, &Subprime.Length);
775 	SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, &Base.Length);
776 	SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, &Value.Length);
777 
778 	switch (pKey->keyalg) {
779 		case KMF_RSA:
780 			/* Get the length of the fields */
781 			rv = C_GetAttributeValue(kmfh->pk11handle,
782 				(CK_OBJECT_HANDLE)pKey->keyp,
783 				rsaTemplate, 4);
784 			if (rv != CKR_OK) {
785 				SET_ERROR(kmfh, rv);
786 				return (KMF_ERR_BAD_PARAMETER);
787 			}
788 
789 			Modulus.Length = rsaTemplate[2].ulValueLen;
790 			Modulus.Data = malloc(Modulus.Length);
791 			if (Modulus.Data == NULL)
792 				return (KMF_ERR_MEMORY);
793 
794 			Exponent.Length = rsaTemplate[3].ulValueLen;
795 			Exponent.Data = malloc(Exponent.Length);
796 			if (Exponent.Data == NULL) {
797 				free(Modulus.Data);
798 				return (KMF_ERR_MEMORY);
799 			}
800 
801 			SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
802 					Modulus.Length);
803 			SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
804 					Exponent.Data, Exponent.Length);
805 			/* Now get the values */
806 			rv = C_GetAttributeValue(kmfh->pk11handle,
807 				(CK_OBJECT_HANDLE)pKey->keyp,
808 				rsaTemplate, 4);
809 			if (rv != CKR_OK) {
810 				SET_ERROR(kmfh, rv);
811 				free(Modulus.Data);
812 				free(Exponent.Data);
813 				return (KMF_ERR_BAD_PARAMETER);
814 			}
815 
816 			/*
817 			 * This is the KEY algorithm, not the
818 			 * signature algorithm.
819 			 */
820 			Algorithm = X509_AlgIdToAlgorithmOid(KMF_ALGID_RSA);
821 			if (Algorithm != NULL) {
822 
823 				/* Encode the RSA Key Data */
824 				if ((asn1 = kmfder_alloc()) == NULL) {
825 					free(Modulus.Data);
826 					free(Exponent.Data);
827 					return (KMF_ERR_MEMORY);
828 				}
829 				if (kmfber_printf(asn1, "{II}",
830 					Modulus.Data, Modulus.Length,
831 					Exponent.Data, Exponent.Length) == -1) {
832 					kmfber_free(asn1, 1);
833 					free(Modulus.Data);
834 					free(Exponent.Data);
835 					return (KMF_ERR_ENCODING);
836 				}
837 				if (kmfber_flatten(asn1, &EncodedKey) == -1) {
838 					kmfber_free(asn1, 1);
839 					free(Modulus.Data);
840 					free(Exponent.Data);
841 					return (KMF_ERR_ENCODING);
842 				}
843 				kmfber_free(asn1, 1);
844 			}
845 
846 			free(Exponent.Data);
847 			free(Modulus.Data);
848 
849 			break;
850 		case KMF_DSA:
851 			/* Get the length of the fields */
852 			rv = C_GetAttributeValue(kmfh->pk11handle,
853 				(CK_OBJECT_HANDLE)pKey->keyp,
854 				dsaTemplate, 6);
855 			if (rv != CKR_OK) {
856 				SET_ERROR(kmfh, rv);
857 				return (KMF_ERR_BAD_PARAMETER);
858 			}
859 			Prime.Length = dsaTemplate[2].ulValueLen;
860 			Prime.Data = malloc(Prime.Length);
861 			if (Prime.Data == NULL) {
862 				return (KMF_ERR_MEMORY);
863 			}
864 
865 			Subprime.Length = dsaTemplate[3].ulValueLen;
866 			Subprime.Data = malloc(Subprime.Length);
867 			if (Subprime.Data == NULL) {
868 				free(Prime.Data);
869 				return (KMF_ERR_MEMORY);
870 			}
871 
872 			Base.Length = dsaTemplate[4].ulValueLen;
873 			Base.Data = malloc(Base.Length);
874 			if (Base.Data == NULL) {
875 				free(Prime.Data);
876 				free(Subprime.Data);
877 				return (KMF_ERR_MEMORY);
878 			}
879 
880 			Value.Length = dsaTemplate[5].ulValueLen;
881 			Value.Data = malloc(Value.Length);
882 			if (Value.Data == NULL) {
883 				free(Prime.Data);
884 				free(Subprime.Data);
885 				free(Base.Data);
886 				return (KMF_ERR_MEMORY);
887 			}
888 			SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
889 					Prime.Length);
890 			SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
891 					Subprime.Length);
892 			SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
893 					Base.Length);
894 			SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
895 					Value.Length);
896 
897 			/* Now get the values */
898 			rv = C_GetAttributeValue(kmfh->pk11handle,
899 				(CK_OBJECT_HANDLE)pKey->keyp,
900 				dsaTemplate, 6);
901 			if (rv != CKR_OK) {
902 				free(Prime.Data);
903 				free(Subprime.Data);
904 				free(Base.Data);
905 				free(Value.Data);
906 				SET_ERROR(kmfh, rv);
907 				return (KMF_ERR_BAD_PARAMETER);
908 			}
909 			/*
910 			 * This is the KEY algorithm, not the
911 			 * signature algorithm.
912 			 */
913 			Algorithm =
914 			    X509_AlgIdToAlgorithmOid(KMF_ALGID_DSA);
915 
916 			/* Encode the DSA Algorithm Parameters */
917 			if ((asn1 = kmfder_alloc()) == NULL) {
918 				free(Prime.Data);
919 				free(Subprime.Data);
920 				free(Base.Data);
921 				free(Value.Data);
922 				return (KMF_ERR_MEMORY);
923 			}
924 
925 			if (kmfber_printf(asn1, "{III}",
926 				Prime.Data, Prime.Length,
927 				Subprime.Data, Subprime.Length,
928 				Base.Data, Base.Length) == -1) {
929 
930 				kmfber_free(asn1, 1);
931 				free(Prime.Data);
932 				free(Subprime.Data);
933 				free(Base.Data);
934 				free(Value.Data);
935 				return (KMF_ERR_ENCODING);
936 			}
937 			if (kmfber_flatten(asn1, &PubKeyParams) == -1) {
938 				kmfber_free(asn1, 1);
939 				free(Prime.Data);
940 				free(Subprime.Data);
941 				free(Base.Data);
942 				free(Value.Data);
943 				return (KMF_ERR_ENCODING);
944 			}
945 			kmfber_free(asn1, 1);
946 			free(Prime.Data);
947 			free(Subprime.Data);
948 			free(Base.Data);
949 
950 			/* Encode the DSA Key Value */
951 			if ((asn1 = kmfder_alloc()) == NULL) {
952 				free(Value.Data);
953 				return (KMF_ERR_MEMORY);
954 			}
955 
956 			if (kmfber_printf(asn1, "I",
957 				Value.Data, Value.Length) == -1) {
958 				kmfber_free(asn1, 1);
959 				free(Value.Data);
960 				return (KMF_ERR_ENCODING);
961 			}
962 			if (kmfber_flatten(asn1, &EncodedKey) == -1) {
963 				kmfber_free(asn1, 1);
964 				free(Value.Data);
965 				return (KMF_ERR_ENCODING);
966 			}
967 			kmfber_free(asn1, 1);
968 			free(Value.Data);
969 			break;
970 		default:
971 			return (KMF_ERR_BAD_PARAMETER);
972 	}
973 
974 	/* Now, build an SPKI structure for the final encoding step */
975 	spki.algorithm.algorithm = *Algorithm;
976 	if (PubKeyParams != NULL) {
977 		spki.algorithm.parameters.Data =
978 			(uchar_t *)PubKeyParams->bv_val;
979 		spki.algorithm.parameters.Length = PubKeyParams->bv_len;
980 	} else {
981 		spki.algorithm.parameters.Data = NULL;
982 		spki.algorithm.parameters.Length = 0;
983 	}
984 
985 	if (EncodedKey != NULL) {
986 		spki.subjectPublicKey.Data = (uchar_t *)EncodedKey->bv_val;
987 		spki.subjectPublicKey.Length = EncodedKey->bv_len;
988 	} else {
989 		spki.subjectPublicKey.Data = NULL;
990 		spki.subjectPublicKey.Length = 0;
991 	}
992 
993 	/* Finally, encode the entire SPKI record */
994 	ret = DerEncodeSPKI(&spki, eData);
995 
996 cleanup:
997 	if (EncodedKey) {
998 		free(EncodedKey->bv_val);
999 		free(EncodedKey);
1000 	}
1001 
1002 	if (PubKeyParams) {
1003 		free(PubKeyParams->bv_val);
1004 		free(PubKeyParams);
1005 	}
1006 
1007 	return (ret);
1008 }
1009 
1010 
1011 static KMF_RETURN
1012 CreateCertObject(KMF_HANDLE_T handle, char *label, KMF_DATA *pcert)
1013 {
1014 	KMF_RETURN rv = 0;
1015 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1016 
1017 	KMF_X509_CERTIFICATE *signed_cert_ptr = NULL;
1018 	KMF_DATA data;
1019 	KMF_DATA Id;
1020 
1021 	CK_RV ckrv;
1022 	CK_ULONG subject_len, issuer_len, serno_len;
1023 	CK_BYTE *subject, *issuer, *serial, nullserno;
1024 	CK_BBOOL true = TRUE;
1025 	CK_CERTIFICATE_TYPE certtype = CKC_X_509;
1026 	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1027 	CK_ATTRIBUTE x509templ[11];
1028 	CK_OBJECT_HANDLE hCert = NULL;
1029 	int i;
1030 
1031 	if (!kmfh)
1032 		return (KMF_ERR_INTERNAL); /* should not happen */
1033 
1034 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
1035 		return (KMF_ERR_INTERNAL); /* should not happen */
1036 
1037 	if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
1038 		return (KMF_ERR_INTERNAL);  /* should not happen */
1039 
1040 	/*
1041 	 * The data *must* be a DER encoded X.509 certificate.
1042 	 * Convert it to a CSSM cert and then parse the fields so
1043 	 * the PKCS#11 attributes can be filled in correctly.
1044 	 */
1045 	rv = DerDecodeSignedCertificate((const KMF_DATA *)pcert,
1046 		&signed_cert_ptr);
1047 	if (rv != KMF_OK) {
1048 		return (KMF_ERR_ENCODING);
1049 	}
1050 
1051 	/*
1052 	 * Encode fields into PKCS#11 attributes.
1053 	 */
1054 
1055 	/* Get the subject name */
1056 	rv = DerEncodeName(&signed_cert_ptr->certificate.subject, &data);
1057 	if (rv == KMF_OK) {
1058 		subject = data.Data;
1059 		subject_len = data.Length;
1060 	} else {
1061 		rv = KMF_ERR_ENCODING;
1062 		goto cleanup;
1063 	}
1064 
1065 	/* Encode the issuer */
1066 	rv = DerEncodeName(&signed_cert_ptr->certificate.issuer, &data);
1067 	if (rv == KMF_OK) {
1068 		issuer = data.Data;
1069 		issuer_len = data.Length;
1070 	} else {
1071 		rv = KMF_ERR_ENCODING;
1072 		goto cleanup;
1073 	}
1074 
1075 	/* Encode serial number */
1076 	if (signed_cert_ptr->certificate.serialNumber.len > 0 &&
1077 	    signed_cert_ptr->certificate.serialNumber.val != NULL) {
1078 		serial = signed_cert_ptr->certificate.serialNumber.val;
1079 		serno_len = signed_cert_ptr->certificate.serialNumber.len;
1080 	} else {
1081 		/*
1082 		 * RFC3280 says to gracefully handle certs with serial numbers
1083 		 * of 0.
1084 		 */
1085 		nullserno = '\0';
1086 		serial  = &nullserno;
1087 		serno_len = 1;
1088 	}
1089 
1090 	/* Generate an ID from the SPKI data */
1091 	rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
1092 			&Id);
1093 
1094 	if (rv != KMF_OK) {
1095 		SET_ERROR(kmfh, rv);
1096 		goto cleanup;
1097 	}
1098 
1099 	i = 0;
1100 	SETATTR(x509templ, i, CKA_CLASS, &certClass,
1101 		sizeof (certClass)); i++;
1102 	SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
1103 		sizeof (certtype)); i++;
1104 	SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
1105 	SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
1106 	SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
1107 	SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
1108 	SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
1109 	SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
1110 	if (label != NULL && strlen(label)) {
1111 		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));
1112 		i++;
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_RV ckrv;
2003 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2004 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
2005 		{ CKA_MODULUS, NULL, 0 },
2006 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
2007 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
2008 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
2009 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
2010 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
2011 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
2012 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
2013 	    };
2014 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2015 	int		i;
2016 
2017 	if ((ckrv = C_GetAttributeValue(sess, obj,
2018 			rsa_pri_attrs, count)) != CKR_OK) {
2019 		SET_ERROR(kmfh, ckrv);
2020 		/* Tell the caller know why the key data cannot be retrieved. */
2021 		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2022 			return (KMF_ERR_SENSITIVE_KEY);
2023 		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2024 			return (KMF_ERR_UNEXTRACTABLE_KEY);
2025 		else
2026 			return (KMF_ERR_INTERNAL);
2027 	}
2028 
2029 	/* Allocate memory for each attribute. */
2030 	for (i = 0; i < count; i++) {
2031 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2032 		    rsa_pri_attrs[i].ulValueLen == 0) {
2033 			rsa_pri_attrs[i].ulValueLen = 0;
2034 			continue;
2035 		}
2036 		if ((rsa_pri_attrs[i].pValue =
2037 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2038 			rv = KMF_ERR_MEMORY;
2039 			goto end;
2040 		}
2041 	}
2042 	/* Now that we have space, really get the attributes */
2043 	if ((rv = C_GetAttributeValue(sess, obj,
2044 			rsa_pri_attrs, count)) != CKR_OK) {
2045 		SET_ERROR(kmfh, rv);
2046 		rv = KMF_ERR_INTERNAL;
2047 		goto end;
2048 	}
2049 	i = 0;
2050 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2051 	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2052 
2053 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2054 	    rsa_pri_attrs[i].ulValueLen != 0)
2055 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->priexp);
2056 	i++;
2057 
2058 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2059 	    rsa_pri_attrs[i].ulValueLen != 0)
2060 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime1);
2061 	i++;
2062 
2063 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2064 	    rsa_pri_attrs[i].ulValueLen != 0)
2065 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->prime2);
2066 	i++;
2067 
2068 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2069 	    rsa_pri_attrs[i].ulValueLen != 0)
2070 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp1);
2071 	i++;
2072 
2073 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2074 	    rsa_pri_attrs[i].ulValueLen != 0)
2075 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->exp2);
2076 	i++;
2077 
2078 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
2079 	    rsa_pri_attrs[i].ulValueLen != 0)
2080 		attr2bigint(&(rsa_pri_attrs[i]), &rawrsa->coef);
2081 	i++;
2082 
2083 end:
2084 	if (rv != KMF_OK) {
2085 		for (i = 0; i < count; i++) {
2086 			if (rsa_pri_attrs[i].pValue != NULL)
2087 				free(rsa_pri_attrs[i].pValue);
2088 		}
2089 		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2090 	}
2091 	return (rv);
2092 }
2093 
2094 static KMF_RETURN
2095 get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2096 {
2097 	KMF_RETURN rv = KMF_OK;
2098 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2099 	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2100 		{ CKA_PRIME, NULL, 0 },
2101 		{ CKA_SUBPRIME, NULL, 0 },
2102 		{ CKA_BASE, NULL, 0 },
2103 		{ CKA_VALUE, NULL, 0 }
2104 	};
2105 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2106 	int		i;
2107 
2108 	if ((rv = C_GetAttributeValue(sess, obj,
2109 		dsa_pri_attrs, count)) != CKR_OK) {
2110 		SET_ERROR(kmfh, rv);
2111 		return (KMF_ERR_INTERNAL);
2112 	}
2113 
2114 	/* Allocate memory for each attribute. */
2115 	for (i = 0; i < count; i++) {
2116 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2117 		    dsa_pri_attrs[i].ulValueLen == 0) {
2118 			dsa_pri_attrs[i].ulValueLen = 0;
2119 			continue;
2120 		}
2121 		if ((dsa_pri_attrs[i].pValue =
2122 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2123 			rv = KMF_ERR_MEMORY;
2124 			goto end;
2125 		}
2126 	}
2127 	if ((rv = C_GetAttributeValue(sess, obj,
2128 		dsa_pri_attrs, count)) != CKR_OK) {
2129 		SET_ERROR(kmfh, rv);
2130 		rv = KMF_ERR_INTERNAL;
2131 		goto end;
2132 	}
2133 
2134 	/* Fill in all the temp variables.  They are all required. */
2135 	i = 0;
2136 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2137 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2138 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2139 	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2140 
2141 end:
2142 	if (rv != KMF_OK) {
2143 		for (i = 0; i < count; i++) {
2144 			if (dsa_pri_attrs[i].pValue != NULL)
2145 				free(dsa_pri_attrs[i].pValue);
2146 		}
2147 		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2148 	}
2149 	return (rv);
2150 }
2151 
2152 static KMF_RETURN
2153 get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2154 {
2155 	KMF_RETURN rv = KMF_OK;
2156 	CK_RV	ckrv;
2157 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2158 	CK_ATTRIBUTE	sym_attr[1];
2159 	CK_ULONG	value_len = 0;
2160 
2161 	/* find the key length first */
2162 	sym_attr[0].type = CKA_VALUE;
2163 	sym_attr[0].pValue = NULL;
2164 	sym_attr[0].ulValueLen = value_len;
2165 	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2166 		/*
2167 		 * Don't return error if the key is sensitive, just
2168 		 * don't return any raw data.  Operations like "list"
2169 		 * need to succeed even if the raw data is not
2170 		 * available.
2171 		 */
2172 		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2173 			rawsym->keydata.val = NULL;
2174 			rawsym->keydata.len = 0;
2175 			return (CKR_OK);
2176 		}
2177 		SET_ERROR(kmfh, ckrv);
2178 		return (KMF_ERR_INTERNAL);
2179 	}
2180 
2181 	/* Allocate memory for pValue */
2182 	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2183 	if (sym_attr[0].pValue == NULL) {
2184 		return (KMF_ERR_MEMORY);
2185 	}
2186 
2187 	/* get the key data */
2188 	if ((rv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2189 		SET_ERROR(kmfh, rv);
2190 		free(sym_attr[0].pValue);
2191 		return (KMF_ERR_INTERNAL);
2192 	}
2193 
2194 	rawsym->keydata.val = sym_attr[0].pValue;
2195 	rawsym->keydata.len = sym_attr[0].ulValueLen;
2196 	return (rv);
2197 }
2198 
2199 static KMF_RETURN
2200 keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2201 	KMF_RAW_KEY_DATA **outkey)
2202 {
2203 	KMF_RETURN rv = KMF_OK;
2204 	KMF_RAW_KEY_DATA *rkey;
2205 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2206 
2207 	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2208 	if (rkey == NULL)
2209 		return (KMF_ERR_MEMORY);
2210 
2211 	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2212 
2213 	rkey->keytype = inkey->keyalg;
2214 
2215 	if (inkey->keyalg == KMF_RSA) {
2216 		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2217 			&rkey->rawdata.rsa);
2218 	} else if (inkey->keyalg == KMF_DSA) {
2219 		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2220 			&rkey->rawdata.dsa);
2221 	} else if (inkey->keyalg == KMF_AES ||
2222 	    inkey->keyalg == KMF_RC4 ||
2223 	    inkey->keyalg == KMF_DES ||
2224 	    inkey->keyalg == KMF_DES3) {
2225 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2226 		    &rkey->rawdata.sym);
2227 	} else {
2228 		rv = KMF_ERR_BAD_PARAMETER;
2229 	}
2230 
2231 	if (rv == KMF_OK) {
2232 		*outkey = rkey;
2233 	} else if (rkey != NULL) {
2234 		free(rkey);
2235 		*outkey = NULL;
2236 	}
2237 
2238 	return (rv);
2239 }
2240 
2241 
2242 static KMF_RETURN
2243 kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2244 {
2245 	switch (keyalg) {
2246 	case KMF_RSA:
2247 		*type = CKK_RSA;
2248 		break;
2249 	case KMF_DSA:
2250 		*type = CKK_DSA;
2251 		break;
2252 	case KMF_AES:
2253 		*type = CKK_AES;
2254 		break;
2255 	case KMF_RC4:
2256 		*type = CKK_RC4;
2257 		break;
2258 	case KMF_DES:
2259 		*type = CKK_DES;
2260 		break;
2261 	case KMF_DES3:
2262 		*type = CKK_DES3;
2263 		break;
2264 	default:
2265 		return (KMF_ERR_BAD_KEY_TYPE);
2266 	}
2267 
2268 	return (KMF_OK);
2269 }
2270 
2271 static int
2272 IDStringToData(char *idstr, KMF_DATA *iddata)
2273 {
2274 	int len, i;
2275 	char *iddup, *byte;
2276 	uint_t lvalue;
2277 
2278 	if (idstr == NULL || !strlen(idstr))
2279 		return (-1);
2280 
2281 	iddup = (char *)strdup(idstr);
2282 	if (iddup == NULL)
2283 		return (KMF_ERR_MEMORY);
2284 
2285 	len = strlen(iddup) / 3  + 1;
2286 	iddata->Data = malloc(len);
2287 	if (iddata->Data == NULL)
2288 		return (KMF_ERR_MEMORY);
2289 	(void) memset(iddata->Data, 0, len);
2290 	iddata->Length = len;
2291 
2292 	byte = strtok(iddup, ":");
2293 	if (byte == NULL) {
2294 		free(iddup);
2295 		free(iddata->Data);
2296 		iddata->Data = NULL;
2297 		iddata->Length = 0;
2298 		return (-1);
2299 	}
2300 
2301 	i = 0;
2302 	do {
2303 		(void) sscanf(byte, "%x", &lvalue);
2304 		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2305 		byte = strtok(NULL, ":");
2306 	} while (byte != NULL && i < len);
2307 
2308 	iddata->Length = i;
2309 	free(iddup);
2310 	return (0);
2311 }
2312 
2313 KMF_RETURN
2314 KMFPK11_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
2315 	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
2316 {
2317 	KMF_RETURN rv = KMF_OK;
2318 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2319 	uint32_t want_keys, i;
2320 	CK_RV ckrv;
2321 	CK_ATTRIBUTE pTmpl[10];
2322 	CK_OBJECT_CLASS class;
2323 	CK_BBOOL true = TRUE;
2324 	CK_ULONG alg;
2325 	CK_BBOOL is_token;
2326 
2327 	if (!kmfh)
2328 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2329 
2330 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2331 		return (KMF_ERR_NO_TOKEN_SELECTED);
2332 
2333 	if (parms == NULL || numkeys == NULL)
2334 		return (KMF_ERR_BAD_PARAMETER);
2335 
2336 	if (numkeys != NULL && *numkeys > 0)
2337 		want_keys = *numkeys;
2338 	else
2339 		want_keys = MAXINT; /* count them all */
2340 
2341 	is_token = parms->pkcs11parms.token;
2342 	if (parms->keyclass == KMF_ASYM_PUB) {
2343 		class = CKO_PUBLIC_KEY;
2344 	} else if (parms->keyclass == KMF_ASYM_PRI) {
2345 		class = CKO_PRIVATE_KEY;
2346 	} else if (parms->keyclass == KMF_SYMMETRIC) {
2347 		class = CKO_SECRET_KEY;
2348 	} else {
2349 		return (KMF_ERR_BAD_KEY_CLASS);
2350 	}
2351 
2352 	i = 0;
2353 	pTmpl[i].type = CKA_TOKEN;
2354 	pTmpl[i].pValue = &is_token;
2355 	pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
2356 	i++;
2357 
2358 	pTmpl[i].type = CKA_CLASS;
2359 	pTmpl[i].pValue = &class;
2360 	pTmpl[i].ulValueLen = sizeof (class);
2361 	i++;
2362 
2363 	if (parms->findLabel != NULL && strlen(parms->findLabel)) {
2364 		pTmpl[i].type = CKA_LABEL;
2365 		pTmpl[i].pValue = parms->findLabel;
2366 		pTmpl[i].ulValueLen = strlen(parms->findLabel);
2367 		i++;
2368 	}
2369 
2370 	if (parms->keytype != 0) {
2371 		rv = kmf2pk11keytype(parms->keytype, &alg);
2372 		if (rv != KMF_OK) {
2373 			return (KMF_ERR_BAD_KEY_TYPE);
2374 		}
2375 		pTmpl[i].type = CKA_KEY_TYPE;
2376 		pTmpl[i].pValue = &alg;
2377 		pTmpl[i].ulValueLen = sizeof (alg);
2378 		i++;
2379 	}
2380 
2381 	if (parms->idstr != NULL) {
2382 		KMF_DATA iddata = { NULL, 0 };
2383 
2384 		/*
2385 		 * ID String parameter is assumed to be of form:
2386 		 * XX:XX:XX:XX:XX ... :XX
2387 		 * where XX is a hex number.
2388 		 *
2389 		 * We must convert this back to binary in order to
2390 		 * use it in a search.
2391 		 */
2392 		rv = IDStringToData(parms->idstr, &iddata);
2393 		if (rv == KMF_OK) {
2394 			pTmpl[i].type = CKA_ID;
2395 			pTmpl[i].pValue = iddata.Data;
2396 			pTmpl[i].ulValueLen = iddata.Length;
2397 			i++;
2398 		} else {
2399 			return (rv);
2400 		}
2401 	}
2402 
2403 	if (parms->pkcs11parms.private) {
2404 		pTmpl[i].type = CKA_PRIVATE;
2405 		pTmpl[i].pValue = &true;
2406 		pTmpl[i].ulValueLen = sizeof (true);
2407 		i++;
2408 	}
2409 
2410 	/*
2411 	 * Authenticate if the object is a token object,
2412 	 * a private or secred key, or if the user passed in credentials.
2413 	 */
2414 	if (parms->cred.credlen > 0) {
2415 		rv = pk11_authenticate(handle, &parms->cred);
2416 		if (rv != KMF_OK) {
2417 			return (rv);
2418 		}
2419 	}
2420 
2421 	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2422 	if (ckrv == CKR_OK) {
2423 		CK_ULONG obj_count, n = 0;
2424 		while (ckrv == CKR_OK && n < want_keys) {
2425 			CK_OBJECT_HANDLE hObj;
2426 
2427 			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2428 				1, &obj_count);
2429 			if (ckrv == CKR_OK && obj_count == 1) {
2430 				if (keys != NULL) {
2431 					CK_ULONG keytype;
2432 					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2433 					keys[n].keyclass = parms->keyclass;
2434 					keys[n].israw = FALSE;
2435 					keys[n].keyp = (void *)hObj;
2436 
2437 					ckrv = getObjectKeytype(handle,
2438 						(CK_OBJECT_HANDLE)keys[n].keyp,
2439 						&keytype);
2440 					if (ckrv != CKR_OK)
2441 						goto end;
2442 
2443 					ckrv = getObjectLabel(handle,
2444 						(CK_OBJECT_HANDLE)keys[n].keyp,
2445 						&(keys[n].keylabel));
2446 					if (ckrv != CKR_OK)
2447 						goto end;
2448 
2449 					if (keytype == CKK_RSA)
2450 						keys[n].keyalg = KMF_RSA;
2451 					else if (keytype == CKK_DSA)
2452 						keys[n].keyalg = KMF_DSA;
2453 					else if (keytype == CKK_AES)
2454 						keys[n].keyalg = KMF_AES;
2455 					else if (keytype == CKK_RC4)
2456 						keys[n].keyalg = KMF_RC4;
2457 					else if (keytype == CKK_DES)
2458 						keys[n].keyalg = KMF_DES;
2459 					else if (keytype == CKK_DES3)
2460 						keys[n].keyalg = KMF_DES3;
2461 
2462 				}
2463 				n++;
2464 			} else {
2465 				break;
2466 			}
2467 		}
2468 		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2469 
2470 		/* "numkeys" indicates the number that were actually found */
2471 		*numkeys = n;
2472 	}
2473 	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
2474 		if (parms->format == KMF_FORMAT_RAWKEY) {
2475 			/* Convert keys to "rawkey" format */
2476 			for (i = 0; i < (*numkeys); i++) {
2477 				KMF_RAW_KEY_DATA *rkey = NULL;
2478 				rv = keyObj2RawKey(handle, &keys[i], &rkey);
2479 				if (rv == KMF_OK) {
2480 					keys[i].keyp = rkey;
2481 					keys[i].israw = TRUE;
2482 				} else {
2483 					break;
2484 				}
2485 			}
2486 		}
2487 	}
2488 end:
2489 	if (ckrv != CKR_OK) {
2490 		SET_ERROR(kmfh, ckrv);
2491 		/* Report authentication failures to the caller */
2492 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2493 		    ckrv == CKR_PIN_INCORRECT ||
2494 		    ckrv == CKR_PIN_INVALID ||
2495 		    ckrv == CKR_PIN_EXPIRED ||
2496 		    ckrv == CKR_PIN_LOCKED ||
2497 		    ckrv == CKR_SESSION_READ_ONLY)
2498 			rv = KMF_ERR_AUTH_FAILED;
2499 		else
2500 			rv = KMF_ERR_INTERNAL;
2501 	} else if ((*numkeys) == 0) {
2502 		rv = KMF_ERR_KEY_NOT_FOUND;
2503 	}
2504 
2505 	return (rv);
2506 }
2507 
2508 static char *
2509 convertDate(char *fulldate)
2510 {
2511 	struct tm tms;
2512 	char newtime[9];
2513 
2514 	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2515 
2516 	if (tms.tm_year < 69)
2517 		tms.tm_year += 100;
2518 
2519 	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2520 
2521 	newtime[8] = 0;
2522 
2523 	/* memory returned must be freed by the caller */
2524 	return ((char *)strdup(newtime));
2525 }
2526 
2527 KMF_RETURN
2528 KMFPK11_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2529 	KMF_RAW_KEY_DATA *rawkey)
2530 {
2531 	KMF_RETURN rv = KMF_OK;
2532 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2533 	int i;
2534 	CK_RV		ckrv = CKR_OK;
2535 	CK_ATTRIBUTE	templ[32];
2536 	CK_OBJECT_HANDLE keyobj;
2537 	CK_KEY_TYPE	keytype;
2538 	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2539 	CK_BBOOL	cktrue = TRUE;
2540 	CK_DATE		startdate, enddate;
2541 	KMF_DATA	id = {NULL, 0};
2542 	KMF_DATA	subject = {NULL, 0};
2543 	KMF_X509EXT_KEY_USAGE kuext;
2544 	KMF_X509_CERTIFICATE *x509 = NULL;
2545 	CK_BBOOL	kufound;
2546 	char		*notbefore = NULL, *start = NULL;
2547 	char		*notafter = NULL, *end = NULL;
2548 
2549 	if (!kmfh)
2550 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2551 
2552 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2553 		return (KMF_ERR_NO_TOKEN_SELECTED);
2554 
2555 	if (params == NULL || params->certificate == NULL ||
2556 		rawkey == NULL)
2557 		return (KMF_ERR_BAD_PARAMETER);
2558 
2559 	if (rawkey->keytype == KMF_RSA)
2560 		keytype = CKK_RSA;
2561 	else if (rawkey->keytype == KMF_DSA)
2562 		keytype = CKK_DSA;
2563 	else
2564 		return (KMF_ERR_BAD_PARAMETER);
2565 
2566 	rv = pk11_authenticate(handle, &params->cred);
2567 	if (rv != KMF_OK) {
2568 		return (rv);
2569 	}
2570 
2571 	id.Data = NULL;
2572 	id.Length = 0;
2573 	rv = KMF_GetCertIDData(params->certificate, &id);
2574 	if (rv != KMF_OK) {
2575 		goto cleanup;
2576 	}
2577 
2578 	rv = DerDecodeSignedCertificate(
2579 		(const KMF_DATA *)params->certificate, &x509);
2580 	if (rv != KMF_OK) {
2581 		goto cleanup;
2582 	}
2583 
2584 	rv = DerEncodeName(&x509->certificate.subject, &subject);
2585 	if (rv != KMF_OK) {
2586 		goto cleanup;
2587 	}
2588 
2589 	rv = KMF_GetCertStartDateString(handle, params->certificate,
2590 		&notbefore);
2591 	if (rv != KMF_OK) {
2592 		goto cleanup;
2593 	}
2594 	start = convertDate(notbefore);
2595 
2596 	rv = KMF_GetCertEndDateString(handle, params->certificate,
2597 		&notafter);
2598 	if (rv != KMF_OK) {
2599 		goto cleanup;
2600 	}
2601 	end = convertDate(notafter);
2602 
2603 	if ((rv = KMF_GetCertKeyUsageExt(params->certificate, &kuext))
2604 		!= KMF_OK && rv != KMF_ERR_EXTENSION_NOT_FOUND)
2605 		goto cleanup;
2606 
2607 	kufound = (rv == KMF_OK);
2608 	rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND above */
2609 
2610 	i = 0;
2611 	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2612 	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2613 	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2614 	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2615 	SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++;
2616 	SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
2617 
2618 	/*
2619 	 * Only set the KeyUsage stuff if the KU extension was present.
2620 	 */
2621 	if (kufound) {
2622 		CK_BBOOL	condition;
2623 
2624 		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
2625 			B_TRUE : B_FALSE;
2626 		SETATTR(templ, i, CKA_UNWRAP, &condition,
2627 			sizeof (CK_BBOOL)); i++;
2628 		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
2629 			B_TRUE : B_FALSE;
2630 		SETATTR(templ, i, CKA_DECRYPT, &condition,
2631 			sizeof (CK_BBOOL)); i++;
2632 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2633 			B_TRUE : B_FALSE;
2634 		SETATTR(templ, i, CKA_SIGN, &condition,
2635 			sizeof (CK_BBOOL)); i++;
2636 		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2637 			B_TRUE : B_FALSE;
2638 		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
2639 			sizeof (CK_BBOOL)); i++;
2640 	}
2641 	if (params->label != NULL) {
2642 		SETATTR(templ, i, CKA_LABEL, params->label,
2643 			strlen(params->label));
2644 		i++;
2645 	}
2646 	if (id.Data != NULL &&
2647 		id.Data != NULL && id.Length > 0) {
2648 		SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2649 		i++;
2650 	}
2651 	if (start != NULL) {
2652 		/*
2653 		 * This make some potentially dangerous assumptions:
2654 		 *  1. that the startdate in the parameter block is
2655 		 * properly formatted as YYYYMMDD
2656 		 *  2. That the CK_DATE structure is always the same.
2657 		 */
2658 		(void) memcpy(&startdate, start, sizeof (CK_DATE));
2659 		SETATTR(templ, i, CKA_START_DATE, &startdate,
2660 			sizeof (startdate));
2661 		i++;
2662 	}
2663 	if (end != NULL) {
2664 		(void) memcpy(&enddate, end, sizeof (CK_DATE));
2665 		SETATTR(templ, i, CKA_END_DATE, &enddate, sizeof (enddate));
2666 		i++;
2667 	}
2668 	if (keytype == CKK_RSA) {
2669 		SETATTR(templ, i, CKA_MODULUS,
2670 			rawkey->rawdata.rsa.mod.val,
2671 			rawkey->rawdata.rsa.mod.len);
2672 		i++;
2673 		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
2674 			rawkey->rawdata.rsa.pubexp.val,
2675 			rawkey->rawdata.rsa.pubexp.len);
2676 		i++;
2677 		if (rawkey->rawdata.rsa.priexp.val != NULL) {
2678 			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
2679 				rawkey->rawdata.rsa.priexp.val,
2680 				rawkey->rawdata.rsa.priexp.len);
2681 			i++;
2682 		}
2683 		if (rawkey->rawdata.rsa.prime1.val != NULL) {
2684 			SETATTR(templ, i, CKA_PRIME_1,
2685 				rawkey->rawdata.rsa.prime1.val,
2686 				rawkey->rawdata.rsa.prime1.len);
2687 			i++;
2688 		}
2689 		if (rawkey->rawdata.rsa.prime2.val != NULL) {
2690 			SETATTR(templ, i, CKA_PRIME_2,
2691 				rawkey->rawdata.rsa.prime2.val,
2692 				rawkey->rawdata.rsa.prime2.len);
2693 			i++;
2694 		}
2695 		if (rawkey->rawdata.rsa.exp1.val != NULL) {
2696 			SETATTR(templ, i, CKA_EXPONENT_1,
2697 				rawkey->rawdata.rsa.exp1.val,
2698 				rawkey->rawdata.rsa.exp1.len);
2699 			i++;
2700 		}
2701 		if (rawkey->rawdata.rsa.exp2.val != NULL) {
2702 			SETATTR(templ, i, CKA_EXPONENT_2,
2703 				rawkey->rawdata.rsa.exp2.val,
2704 				rawkey->rawdata.rsa.exp2.len);
2705 			i++;
2706 		}
2707 		if (rawkey->rawdata.rsa.coef.val != NULL) {
2708 			SETATTR(templ, i, CKA_COEFFICIENT,
2709 				rawkey->rawdata.rsa.coef.val,
2710 				rawkey->rawdata.rsa.coef.len);
2711 			i++;
2712 		}
2713 	} else {
2714 		SETATTR(templ, i, CKA_PRIME,
2715 			rawkey->rawdata.dsa.prime.val,
2716 			rawkey->rawdata.dsa.prime.len);
2717 		i++;
2718 		SETATTR(templ, i, CKA_SUBPRIME,
2719 			rawkey->rawdata.dsa.subprime.val,
2720 			rawkey->rawdata.dsa.subprime.len);
2721 		i++;
2722 		SETATTR(templ, i, CKA_BASE,
2723 			rawkey->rawdata.dsa.base.val,
2724 			rawkey->rawdata.dsa.base.len);
2725 		i++;
2726 		SETATTR(templ, i, CKA_VALUE,
2727 			rawkey->rawdata.dsa.value.val,
2728 			rawkey->rawdata.dsa.value.len);
2729 		i++;
2730 	}
2731 
2732 	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
2733 	if (ckrv != CKR_OK) {
2734 		SET_ERROR(kmfh, ckrv);
2735 
2736 		/* Report authentication failures to the caller */
2737 		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2738 		    ckrv == CKR_PIN_INCORRECT ||
2739 		    ckrv == CKR_PIN_INVALID ||
2740 		    ckrv == CKR_PIN_EXPIRED ||
2741 		    ckrv == CKR_PIN_LOCKED ||
2742 		    ckrv == CKR_SESSION_READ_ONLY)
2743 			rv = KMF_ERR_AUTH_FAILED;
2744 		else
2745 			rv = KMF_ERR_INTERNAL;
2746 	}
2747 cleanup:
2748 	KMF_FreeData(&id);
2749 	KMF_FreeData(&subject);
2750 	KMF_FreeSignedCert(x509);
2751 	free(x509);
2752 
2753 	return (rv);
2754 }
2755 
2756 KMF_RETURN
2757 KMFPK11_CreateSymKey(KMF_HANDLE_T handle, KMF_CREATESYMKEY_PARAMS *params,
2758 	KMF_KEY_HANDLE *symkey)
2759 {
2760 	KMF_RETURN		rv = KMF_OK;
2761 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2762 	CK_RV			ckrv;
2763 	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
2764 	CK_OBJECT_HANDLE	keyhandle;
2765 	CK_MECHANISM		keyGenMech;
2766 	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
2767 	CK_ULONG		secKeyType;
2768 	CK_ULONG		secKeyLen;	/* for RC4 and AES */
2769 	CK_BBOOL		true = TRUE;
2770 	CK_BBOOL		false = FALSE;
2771 	CK_ATTRIBUTE		templ[15];
2772 	int i;
2773 
2774 	if (kmfh == NULL)
2775 		return (KMF_ERR_UNINITIALIZED);
2776 
2777 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2778 		return (KMF_ERR_NO_TOKEN_SELECTED);
2779 
2780 	if (params == NULL)
2781 		return (KMF_ERR_BAD_PARAMETER);
2782 
2783 	keyGenMech.pParameter = NULL_PTR;
2784 	keyGenMech.ulParameterLen = 0;
2785 	switch (params->keytype) {
2786 	case KMF_AES:
2787 		keyGenMech.mechanism = CKM_AES_KEY_GEN;
2788 		secKeyType = CKK_AES;
2789 		break;
2790 	case KMF_RC4:
2791 		keyGenMech.mechanism = CKM_RC4_KEY_GEN;
2792 		secKeyType = CKK_RC4;
2793 		break;
2794 	case KMF_DES:
2795 		keyGenMech.mechanism = CKM_DES_KEY_GEN;
2796 		secKeyType = CKK_DES;
2797 		break;
2798 	case KMF_DES3:
2799 		keyGenMech.mechanism = CKM_DES3_KEY_GEN;
2800 		secKeyType = CKK_DES3;
2801 		break;
2802 	default:
2803 		return (KMF_ERR_BAD_KEY_TYPE);
2804 	}
2805 
2806 	i = 0;
2807 	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2808 	i++;
2809 	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2810 	i++;
2811 
2812 	if (params->keytype == KMF_AES || params->keytype == KMF_RC4) {
2813 		if ((params->keylength % 8) != 0) {
2814 			return (KMF_ERR_BAD_KEY_SIZE);
2815 		}
2816 		secKeyLen = params->keylength/8;  /* in bytes for RC4/AES */
2817 		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
2818 		    sizeof (secKeyLen));
2819 		i++;
2820 	}
2821 
2822 	if (params->keylabel != NULL) {
2823 		SETATTR(templ, i, CKA_LABEL, params->keylabel,
2824 		    strlen(params->keylabel));
2825 		i++;
2826 	}
2827 
2828 	if (params->pkcs11parms.sensitive == B_TRUE) {
2829 		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2830 	} else {
2831 		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2832 	}
2833 	i++;
2834 
2835 	if (params->pkcs11parms.not_extractable == B_TRUE) {
2836 		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2837 	} else {
2838 		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2839 	}
2840 	i++;
2841 
2842 	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2843 	i++;
2844 	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2845 	i++;
2846 	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
2847 	i++;
2848 	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
2849 	i++;
2850 	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2851 	i++;
2852 	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
2853 	i++;
2854 
2855 	rv = pk11_authenticate(handle, &params->cred);
2856 	if (rv != KMF_OK) {
2857 		return (rv);
2858 	}
2859 
2860 	ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i, &keyhandle);
2861 	if (ckrv != CKR_OK) {
2862 		SET_ERROR(kmfh, ckrv);
2863 		rv = KMF_ERR_KEYGEN_FAILED;
2864 		goto out;
2865 	}
2866 
2867 	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2868 	symkey->keyalg = params->keytype;
2869 	symkey->keyclass = KMF_SYMMETRIC;
2870 	symkey->israw = FALSE;
2871 	symkey->keyp = (void *)keyhandle;
2872 
2873 out:
2874 	return (rv);
2875 }
2876 
2877 
2878 KMF_RETURN
2879 KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2880     KMF_RAW_SYM_KEY *rkey)
2881 {
2882 	KMF_RETURN		rv = KMF_OK;
2883 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
2884 
2885 	if (kmfh == NULL)
2886 		return (KMF_ERR_UNINITIALIZED);
2887 
2888 	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2889 		return (KMF_ERR_NO_TOKEN_SELECTED);
2890 
2891 	if (symkey == NULL || rkey == NULL)
2892 		return (KMF_ERR_BAD_PARAMETER);
2893 	else if (symkey->keyclass != KMF_SYMMETRIC)
2894 		return (KMF_ERR_BAD_KEY_CLASS);
2895 
2896 	if (symkey->israw) {
2897 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2898 
2899 		if (rawkey == NULL ||
2900 		    rawkey->rawdata.sym.keydata.val == NULL ||
2901 		    rawkey->rawdata.sym.keydata.len == 0)
2902 			return (KMF_ERR_BAD_KEYHANDLE);
2903 
2904 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2905 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2906 			return (KMF_ERR_MEMORY);
2907 		(void) memcpy(rkey->keydata.val,
2908 			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2909 	} else {
2910 		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
2911 	}
2912 
2913 	return (rv);
2914 }
2915 
2916 KMF_RETURN
2917 KMFPK11_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2918 	KMF_CREDENTIAL *newpin)
2919 {
2920 	KMF_RETURN	ret = KMF_OK;
2921 	CK_RV		rv = CKR_OK;
2922 	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
2923 	CK_SESSION_HANDLE	session = NULL;
2924 
2925 	if (handle == NULL || params == NULL || newpin == NULL)
2926 		return (KMF_ERR_BAD_PARAMETER);
2927 
2928 	rv = C_OpenSession(params->pkcs11parms.slot,
2929 		CKF_SERIAL_SESSION | CKF_RW_SESSION,
2930 		NULL, NULL, &session);
2931 	if (rv != CKR_OK) {
2932 		SET_ERROR(kmfh, rv);
2933 		ret = KMF_ERR_UNINITIALIZED;
2934 		goto end;
2935 	}
2936 
2937 	rv = C_SetPIN(session,
2938 		(CK_BYTE *)params->cred.cred, params->cred.credlen,
2939 		(CK_BYTE *)newpin->cred, newpin->credlen);
2940 
2941 	if (rv != CKR_OK) {
2942 		SET_ERROR(kmfh, rv);
2943 		if (rv == CKR_PIN_INCORRECT ||
2944 		    rv == CKR_PIN_INVALID ||
2945 		    rv == CKR_PIN_EXPIRED ||
2946 		    rv == CKR_PIN_LOCKED)
2947 			ret = KMF_ERR_AUTH_FAILED;
2948 		else
2949 			ret = KMF_ERR_INTERNAL;
2950 	}
2951 end:
2952 	if (session != NULL)
2953 		(void) C_CloseSession(session);
2954 	return (ret);
2955 }
2956