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