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