pkcs11_spi.c revision 6051:7b29d160facb
11573Srgrimes/*
21573Srgrimes * CDDL HEADER START
31573Srgrimes *
41573Srgrimes * The contents of this file are subject to the terms of the
51573Srgrimes * Common Development and Distribution License (the "License").
61573Srgrimes * You may not use this file except in compliance with the License.
71573Srgrimes *
81573Srgrimes * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91573Srgrimes * or http://www.opensolaris.org/os/licensing.
101573Srgrimes * See the License for the specific language governing permissions
111573Srgrimes * and limitations under the License.
121573Srgrimes *
131573Srgrimes * When distributing Covered Code, include this CDDL HEADER in each
141573Srgrimes * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151573Srgrimes * If applicable, add the following below this CDDL HEADER, with the
16148834Sstefanf * fields enclosed by brackets "[]" replaced with your own identifying
171573Srgrimes * information: Portions Copyright [yyyy] [name of copyright owner]
181573Srgrimes *
191573Srgrimes * CDDL HEADER END
201573Srgrimes */
211573Srgrimes/*
221573Srgrimes * PKCS11 token KMF Plugin
231573Srgrimes *
241573Srgrimes * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
251573Srgrimes * Use is subject to license terms.
261573Srgrimes */
271573Srgrimes
281573Srgrimes#pragma ident	"%Z%%M%	%I%	%E% SMI"
291573Srgrimes
301573Srgrimes#include <stdio.h> /* debugging only */
311573Srgrimes#include <errno.h>
321573Srgrimes#include <values.h>
33148834Sstefanf
3484260Sobrien#include <kmfapiP.h>
351573Srgrimes#include <ber_der.h>
361573Srgrimes#include <algorithm.h>
371573Srgrimes#include <fcntl.h>
381573Srgrimes#include <sha1.h>
391573Srgrimes#include <bignum.h>
401573Srgrimes
4184260Sobrien#include <cryptoutil.h>
421573Srgrimes#include <security/cryptoki.h>
431573Srgrimes#include <security/pkcs11.h>
441573Srgrimes
4584260Sobrien#define	DEV_RANDOM	"/dev/random"
461573Srgrimes
471573Srgrimes#define	SETATTR(t, n, atype, value, size) \
4884260Sobrien	t[n].type = atype; \
4984260Sobrien	t[n].pValue = (CK_BYTE *)value; \
5084260Sobrien	t[n].ulValueLen = (CK_ULONG)size;
5184260Sobrien
5284260Sobrien#define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; \
5384260Sobrien	h->lasterr.errcode = c;
5484260Sobrien
551573Srgrimestypedef struct _objlist {
561573Srgrimes	CK_OBJECT_HANDLE handle;
5784260Sobrien	struct _objlist *next;
5884260Sobrien} OBJLIST;
5984260Sobrien
601573Srgrimesstatic KMF_RETURN
611573Srgrimessearch_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
621573Srgrimes	boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
631573Srgrimes
641573Srgrimesstatic CK_RV
65148834SstefanfgetObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
6684260Sobrien
6784260Sobrienstatic KMF_RETURN
681573SrgrimeskeyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
6984260Sobrien
7084260Sobrienstatic KMF_RETURN
7184260Sobriencreate_generic_secret_key(KMF_HANDLE_T,
7284260Sobrien	int, KMF_ATTRIBUTE *, CK_OBJECT_HANDLE *);
73148834Sstefanf
7484260SobrienKMF_RETURN
751573SrgrimesKMFPK11_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
761573Srgrimes
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
2176static KMF_RETURN
2177get_bigint_attr(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
2178	CK_ATTRIBUTE_TYPE attrtype, KMF_BIGINT *bigint)
2179{
2180	CK_RV ckrv;
2181	CK_ATTRIBUTE attr;
2182
2183	attr.type = attrtype;
2184	attr.pValue = NULL;
2185	attr.ulValueLen = 0;
2186
2187	if ((ckrv = C_GetAttributeValue(sess, obj,
2188	    &attr, 1)) != CKR_OK) {
2189		/* Mask this error so the caller can continue */
2190		if (ckrv == CKR_ATTRIBUTE_TYPE_INVALID)
2191			return (KMF_OK);
2192		else
2193			return (KMF_ERR_INTERNAL);
2194	}
2195	if (attr.ulValueLen > 0 && bigint != NULL) {
2196		attr.pValue = malloc(attr.ulValueLen);
2197		if (attr.pValue == NULL)
2198			return (KMF_ERR_MEMORY);
2199
2200		if ((ckrv = C_GetAttributeValue(sess, obj,
2201		    &attr, 1)) != CKR_OK)
2202		if (ckrv != CKR_OK) {
2203			free(attr.pValue);
2204			return (KMF_ERR_INTERNAL);
2205		}
2206
2207		bigint->val = attr.pValue;
2208		bigint->len = attr.ulValueLen;
2209	}
2210	return (KMF_OK);
2211}
2212
2213static KMF_RETURN
2214get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2215{
2216	KMF_RETURN rv = KMF_OK;
2217	CK_RV ckrv;
2218	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2219	CK_ATTRIBUTE rsa_pri_attrs[2] = {
2220		{ CKA_MODULUS, NULL, 0 },
2221		{ CKA_PUBLIC_EXPONENT, NULL, 0 }
2222	};
2223	CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2224	int i;
2225
2226	if (rawrsa == NULL)
2227		return (KMF_ERR_BAD_PARAMETER);
2228
2229	(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2230	if ((ckrv = C_GetAttributeValue(sess, obj,
2231	    rsa_pri_attrs, count)) != CKR_OK) {
2232		SET_ERROR(kmfh, ckrv);
2233		/* Tell the caller know why the key data cannot be retrieved. */
2234		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2235			return (KMF_ERR_SENSITIVE_KEY);
2236		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2237			return (KMF_ERR_UNEXTRACTABLE_KEY);
2238		else
2239			return (KMF_ERR_INTERNAL);
2240	}
2241
2242	/* Allocate memory for each attribute. */
2243	for (i = 0; i < count; i++) {
2244		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2245		    rsa_pri_attrs[i].ulValueLen == 0) {
2246			rsa_pri_attrs[i].ulValueLen = 0;
2247			continue;
2248		}
2249		if ((rsa_pri_attrs[i].pValue =
2250		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2251			rv = KMF_ERR_MEMORY;
2252			goto end;
2253		}
2254	}
2255	/* Now that we have space, really get the attributes */
2256	if ((rv = C_GetAttributeValue(sess, obj,
2257	    rsa_pri_attrs, count)) != CKR_OK) {
2258		SET_ERROR(kmfh, rv);
2259		rv = KMF_ERR_INTERNAL;
2260		goto end;
2261	}
2262	i = 0;
2263	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2264	attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2265
2266	/* Now get the optional parameters */
2267	rv = get_bigint_attr(sess, obj, CKA_PRIVATE_EXPONENT, &rawrsa->priexp);
2268	if (rv != KMF_OK)
2269		goto end;
2270	rv = get_bigint_attr(sess, obj, CKA_PRIME_1, &rawrsa->prime1);
2271	if (rv != KMF_OK)
2272		goto end;
2273	rv = get_bigint_attr(sess, obj, CKA_PRIME_2, &rawrsa->prime2);
2274	if (rv != KMF_OK)
2275		goto end;
2276	rv = get_bigint_attr(sess, obj, CKA_EXPONENT_1, &rawrsa->exp1);
2277	if (rv != KMF_OK)
2278		goto end;
2279	rv = get_bigint_attr(sess, obj, CKA_EXPONENT_2, &rawrsa->exp2);
2280	if (rv != KMF_OK)
2281		goto end;
2282	rv = get_bigint_attr(sess, obj, CKA_COEFFICIENT, &rawrsa->coef);
2283	if (rv != KMF_OK)
2284		goto end;
2285
2286end:
2287	if (rv != KMF_OK) {
2288		for (i = 0; i < count; i++) {
2289			if (rsa_pri_attrs[i].pValue != NULL)
2290				free(rsa_pri_attrs[i].pValue);
2291		}
2292		if (rawrsa->priexp.val)
2293			free(rawrsa->priexp.val);
2294		if (rawrsa->prime1.val)
2295			free(rawrsa->prime1.val);
2296		if (rawrsa->prime2.val)
2297			free(rawrsa->prime2.val);
2298		if (rawrsa->exp1.val)
2299			free(rawrsa->exp1.val);
2300		if (rawrsa->exp2.val)
2301			free(rawrsa->exp2.val);
2302		if (rawrsa->coef.val)
2303			free(rawrsa->coef.val);
2304		(void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2305	}
2306	return (rv);
2307}
2308
2309#define	DSA_PRIME_BUFSIZE	256	/* 8192 bits */
2310#define	DSA_PRIVATE_BUFSIZE	5	/* 160 bits */
2311
2312/*
2313 * This function calculates the pubkey value from the prime,
2314 * base and private key values of a DSA key.
2315 */
2316static KMF_RETURN
2317compute_dsa_pubvalue(KMF_RAW_DSA_KEY *rawdsa)
2318{
2319	KMF_RETURN rv = KMF_OK;
2320	BIGNUM p, g, x, y;
2321	BIG_ERR_CODE err;
2322	uchar_t *pubvalue;
2323	uint32_t pubvalue_len;
2324
2325	if ((err = big_init1(&p, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2326		rv = KMF_ERR_MEMORY;
2327		return (rv);
2328	}
2329	bytestring2bignum(&p, rawdsa->prime.val, rawdsa->prime.len);
2330
2331	if ((err = big_init1(&g, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2332		rv = KMF_ERR_MEMORY;
2333		goto ret1;
2334	}
2335	bytestring2bignum(&g, rawdsa->base.val, rawdsa->base.len);
2336
2337	if ((err = big_init1(&x, DSA_PRIVATE_BUFSIZE, NULL, 0)) != BIG_OK) {
2338		rv = KMF_ERR_MEMORY;
2339		goto ret2;
2340	}
2341	bytestring2bignum(&x, rawdsa->value.val, rawdsa->value.len);
2342
2343	if ((err = big_init1(&y, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2344		rv = KMF_ERR_MEMORY;
2345		goto ret3;
2346	}
2347
2348	err = big_modexp(&y, &g, &x, &p, NULL);
2349	if (err != BIG_OK) {
2350		rv = KMF_ERR_INTERNAL;
2351		goto ret3;
2352	}
2353
2354	pubvalue_len = y.len * (int)sizeof (uint32_t);
2355	if ((pubvalue = malloc(pubvalue_len)) == NULL) {
2356		rv = KMF_ERR_MEMORY;
2357		goto ret4;
2358	}
2359	bignum2bytestring(pubvalue, &y, pubvalue_len);
2360
2361	rawdsa->pubvalue.val = pubvalue;
2362	rawdsa->pubvalue.len = pubvalue_len;
2363
2364ret4:
2365	big_finish(&y);
2366ret3:
2367	big_finish(&x);
2368ret2:
2369	big_finish(&g);
2370ret1:
2371	big_finish(&p);
2372	return (rv);
2373}
2374
2375
2376static KMF_RETURN
2377get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2378{
2379	KMF_RETURN rv = KMF_OK;
2380	CK_RV ckrv;
2381	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2382	CK_ATTRIBUTE	dsa_pri_attrs[8] = {
2383		{ CKA_PRIME, NULL, 0 },
2384		{ CKA_SUBPRIME, NULL, 0 },
2385		{ CKA_BASE, NULL, 0 },
2386		{ CKA_VALUE, NULL, 0 }
2387	};
2388	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2389	int		i;
2390
2391	if ((ckrv = C_GetAttributeValue(sess, obj,
2392	    dsa_pri_attrs, count)) != CKR_OK) {
2393		SET_ERROR(kmfh, ckrv);
2394
2395		/* Tell the caller know why the key data cannot be retrieved. */
2396		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2397			return (KMF_ERR_SENSITIVE_KEY);
2398		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2399			return (KMF_ERR_UNEXTRACTABLE_KEY);
2400		return (KMF_ERR_INTERNAL);
2401	}
2402
2403	/* Allocate memory for each attribute. */
2404	for (i = 0; i < count; i++) {
2405		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2406		    dsa_pri_attrs[i].ulValueLen == 0) {
2407			dsa_pri_attrs[i].ulValueLen = 0;
2408			continue;
2409		}
2410		if ((dsa_pri_attrs[i].pValue =
2411		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2412			rv = KMF_ERR_MEMORY;
2413			goto end;
2414		}
2415	}
2416	if ((rv = C_GetAttributeValue(sess, obj,
2417	    dsa_pri_attrs, count)) != CKR_OK) {
2418		SET_ERROR(kmfh, rv);
2419		rv = KMF_ERR_INTERNAL;
2420		goto end;
2421	}
2422
2423	/* Fill in all the temp variables.  They are all required. */
2424	i = 0;
2425	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2426	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2427	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2428	attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2429
2430	/* Compute the public key value and store it */
2431	rv = compute_dsa_pubvalue(rawdsa);
2432
2433end:
2434	if (rv != KMF_OK) {
2435		for (i = 0; i < count; i++) {
2436			if (dsa_pri_attrs[i].pValue != NULL)
2437				free(dsa_pri_attrs[i].pValue);
2438		}
2439		(void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2440	}
2441	return (rv);
2442}
2443
2444static KMF_RETURN
2445get_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2446{
2447	KMF_RETURN rv = KMF_OK;
2448	CK_RV	ckrv;
2449	CK_SESSION_HANDLE sess = kmfh->pk11handle;
2450	CK_ATTRIBUTE	sym_attr[1];
2451	CK_ULONG	value_len = 0;
2452
2453	/* find the key length first */
2454	sym_attr[0].type = CKA_VALUE;
2455	sym_attr[0].pValue = NULL;
2456	sym_attr[0].ulValueLen = value_len;
2457	if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2458		rawsym->keydata.val = NULL;
2459		rawsym->keydata.len = 0;
2460		if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2461			return (KMF_ERR_SENSITIVE_KEY);
2462		} else if (ckrv == CKR_KEY_UNEXTRACTABLE) {
2463			return (KMF_ERR_UNEXTRACTABLE_KEY);
2464		} else {
2465			SET_ERROR(kmfh, ckrv);
2466			return (KMF_ERR_INTERNAL);
2467		}
2468	}
2469
2470	/* Allocate memory for pValue */
2471	sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2472	if (sym_attr[0].pValue == NULL) {
2473		return (KMF_ERR_MEMORY);
2474	}
2475
2476	/* get the key data */
2477	if ((rv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2478		SET_ERROR(kmfh, rv);
2479		free(sym_attr[0].pValue);
2480		return (KMF_ERR_INTERNAL);
2481	}
2482
2483	rawsym->keydata.val = sym_attr[0].pValue;
2484	rawsym->keydata.len = sym_attr[0].ulValueLen;
2485	return (rv);
2486}
2487
2488static KMF_RETURN
2489keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2490	KMF_RAW_KEY_DATA **outkey)
2491{
2492	KMF_RETURN rv = KMF_OK;
2493	KMF_RAW_KEY_DATA *rkey;
2494	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2495
2496	rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2497	if (rkey == NULL)
2498		return (KMF_ERR_MEMORY);
2499
2500	(void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2501
2502	rkey->keytype = inkey->keyalg;
2503
2504	if (inkey->keyalg == KMF_RSA) {
2505		rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2506		    &rkey->rawdata.rsa);
2507	} else if (inkey->keyalg == KMF_DSA) {
2508		rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2509		    &rkey->rawdata.dsa);
2510	} else if (inkey->keyalg == KMF_AES ||
2511	    inkey->keyalg == KMF_RC4 ||
2512	    inkey->keyalg == KMF_DES ||
2513	    inkey->keyalg == KMF_DES3 ||
2514	    inkey->keyalg == KMF_GENERIC_SECRET) {
2515		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2516		    &rkey->rawdata.sym);
2517		/*
2518		 * If sensitive or non-extractable, mark them as such
2519		 * but return "OK" status so the keys get counted
2520		 * when doing FindKey operations.
2521		 */
2522		if (rv == KMF_ERR_SENSITIVE_KEY) {
2523			rkey->sensitive = B_TRUE;
2524			rv = KMF_OK;
2525		} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
2526			rkey->not_extractable = B_TRUE;
2527			rv = KMF_OK;
2528		}
2529	} else {
2530		rv = KMF_ERR_BAD_PARAMETER;
2531	}
2532
2533	if (rv == KMF_OK) {
2534		*outkey = rkey;
2535	} else if (rkey != NULL) {
2536		free(rkey);
2537		*outkey = NULL;
2538	}
2539
2540	return (rv);
2541}
2542
2543
2544static KMF_RETURN
2545kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2546{
2547	switch (keyalg) {
2548	case KMF_RSA:
2549		*type = CKK_RSA;
2550		break;
2551	case KMF_DSA:
2552		*type = CKK_DSA;
2553		break;
2554	case KMF_AES:
2555		*type = CKK_AES;
2556		break;
2557	case KMF_RC4:
2558		*type = CKK_RC4;
2559		break;
2560	case KMF_DES:
2561		*type = CKK_DES;
2562		break;
2563	case KMF_DES3:
2564		*type = CKK_DES3;
2565		break;
2566	case KMF_GENERIC_SECRET:
2567		*type = CKK_GENERIC_SECRET;
2568		break;
2569	default:
2570		return (KMF_ERR_BAD_KEY_TYPE);
2571	}
2572
2573	return (KMF_OK);
2574}
2575
2576static int
2577IDStringToData(char *idstr, KMF_DATA *iddata)
2578{
2579	int len, i;
2580	char *iddup, *byte;
2581	uint_t lvalue;
2582
2583	if (idstr == NULL || !strlen(idstr))
2584		return (-1);
2585
2586	iddup = (char *)strdup(idstr);
2587	if (iddup == NULL)
2588		return (KMF_ERR_MEMORY);
2589
2590	len = strlen(iddup) / 3  + 1;
2591	iddata->Data = malloc(len);
2592	if (iddata->Data == NULL)
2593		return (KMF_ERR_MEMORY);
2594	(void) memset(iddata->Data, 0, len);
2595	iddata->Length = len;
2596
2597	byte = strtok(iddup, ":");
2598	if (byte == NULL) {
2599		free(iddup);
2600		free(iddata->Data);
2601		iddata->Data = NULL;
2602		iddata->Length = 0;
2603		return (-1);
2604	}
2605
2606	i = 0;
2607	do {
2608		(void) sscanf(byte, "%x", &lvalue);
2609		iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2610		byte = strtok(NULL, ":");
2611	} while (byte != NULL && i < len);
2612
2613	iddata->Length = i;
2614	free(iddup);
2615	return (0);
2616}
2617
2618KMF_RETURN
2619KMFPK11_FindKey(KMF_HANDLE_T handle,
2620	int numattr, KMF_ATTRIBUTE *attrlist)
2621{
2622	KMF_RETURN rv = KMF_OK;
2623	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2624	uint32_t want_keys, i;
2625	CK_RV ckrv;
2626	CK_ATTRIBUTE pTmpl[10];
2627	CK_OBJECT_CLASS class;
2628	CK_BBOOL true = TRUE;
2629	CK_ULONG alg;
2630	boolean_t is_token = B_TRUE, is_private = B_FALSE;
2631	KMF_KEY_HANDLE *keys;
2632	uint32_t *numkeys;
2633	KMF_CREDENTIAL *cred = NULL;
2634	KMF_KEY_CLASS keyclass = KMF_KEYCLASS_NONE;
2635	char *findLabel, *idstr;
2636	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
2637	KMF_ENCODE_FORMAT format;
2638
2639	if (kmfh == NULL)
2640		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2641
2642	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2643		return (KMF_ERR_NO_TOKEN_SELECTED);
2644
2645	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2646	if (numkeys == NULL)
2647		return (KMF_ERR_BAD_PARAMETER);
2648
2649	if (*numkeys > 0)
2650		want_keys = *numkeys;
2651	else
2652		want_keys = MAXINT; /* count them all */
2653
2654	/* keyclass is optional */
2655	(void) kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2656	    (void *)&keyclass, NULL);
2657
2658	if (keyclass == KMF_ASYM_PUB) {
2659		class = CKO_PUBLIC_KEY;
2660	} else if (keyclass == KMF_ASYM_PRI) {
2661		class = CKO_PRIVATE_KEY;
2662	} else if (keyclass == KMF_SYMMETRIC) {
2663		class = CKO_SECRET_KEY;
2664	}
2665
2666	rv = kmf_get_attr(KMF_TOKEN_BOOL_ATTR, attrlist, numattr,
2667	    (void *)&is_token, NULL);
2668	if (rv != KMF_OK)
2669		return (rv);
2670
2671	i = 0;
2672	if (is_token) {
2673		SETATTR(pTmpl, i, CKA_TOKEN, &true, sizeof (true));
2674		i++;
2675	}
2676
2677	if (keyclass != KMF_KEYCLASS_NONE) {
2678		SETATTR(pTmpl, i, CKA_CLASS, &class, sizeof (class));
2679		i++;
2680	}
2681
2682	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2683
2684	if (findLabel != NULL && strlen(findLabel)) {
2685		SETATTR(pTmpl, i, CKA_LABEL, findLabel, strlen(findLabel));
2686		i++;
2687	}
2688	/* keytype is optional */
2689	(void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2690	    (void *)&keytype, NULL);
2691
2692	if (keytype != 0) {
2693		rv = kmf2pk11keytype(keytype, &alg);
2694		if (rv != KMF_OK) {
2695			return (KMF_ERR_BAD_KEY_TYPE);
2696		}
2697		SETATTR(pTmpl, i, CKA_KEY_TYPE, &alg, sizeof (alg));
2698		i++;
2699	}
2700
2701	idstr = kmf_get_attr_ptr(KMF_IDSTR_ATTR, attrlist, numattr);
2702
2703	if (idstr != NULL) {
2704		KMF_DATA iddata = { NULL, 0 };
2705
2706		/*
2707		 * ID String parameter is assumed to be of form:
2708		 * XX:XX:XX:XX:XX ... :XX
2709		 * where XX is a hex number.
2710		 *
2711		 * We must convert this back to binary in order to
2712		 * use it in a search.
2713		 */
2714		rv = IDStringToData(idstr, &iddata);
2715		if (rv == KMF_OK) {
2716			SETATTR(pTmpl, i, CKA_ID, iddata.Data, iddata.Length);
2717			i++;
2718		} else {
2719			return (rv);
2720		}
2721	}
2722
2723	/* is_private is optional */
2724	(void) kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
2725	    (void *)&is_private, NULL);
2726
2727	if (is_private) {
2728		SETATTR(pTmpl, i, CKA_PRIVATE, &true, sizeof (true));
2729		i++;
2730	}
2731
2732	/*
2733	 * Authenticate if the object is a token object,
2734	 * a private or secred key, or if the user passed in credentials.
2735	 */
2736	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2737	if (cred != NULL && (cred->credlen > 0)) {
2738		rv = pk11_authenticate(handle, cred);
2739		if (rv != KMF_OK)
2740			return (rv);
2741	}
2742
2743	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2744	/* it is okay to have "keys" contains NULL */
2745
2746	ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2747	if (ckrv == CKR_OK) {
2748		CK_ULONG obj_count, n = 0;
2749		while (ckrv == CKR_OK && n < want_keys) {
2750			CK_OBJECT_HANDLE hObj;
2751
2752			ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2753			    1, &obj_count);
2754			if (ckrv == CKR_OK && obj_count == 1) {
2755				if (keys != NULL) {
2756					CK_ULONG keytype;
2757					keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2758					keys[n].israw = FALSE;
2759					keys[n].keyp = (void *)hObj;
2760
2761					ckrv = getObjectKeytype(handle,
2762					    (CK_OBJECT_HANDLE)keys[n].keyp,
2763					    &keytype);
2764					if (ckrv != CKR_OK)
2765						goto end;
2766
2767					ckrv = getObjectLabel(handle,
2768					    (CK_OBJECT_HANDLE)keys[n].keyp,
2769					    &(keys[n].keylabel));
2770					if (ckrv != CKR_OK)
2771						goto end;
2772
2773					if (keyclass == KMF_KEYCLASS_NONE) {
2774						ckrv = getObjectKeyclass(handle,
2775						    (CK_OBJECT_HANDLE)
2776						    keys[n].keyp,
2777						    &(keys[n].keyclass));
2778						if (ckrv != CKR_OK)
2779							goto end;
2780					} else {
2781						keys[n].keyclass = keyclass;
2782					}
2783					if (keytype == CKK_RSA) {
2784						keys[n].keyalg = KMF_RSA;
2785					} else if (keytype == CKK_DSA) {
2786						keys[n].keyalg = KMF_DSA;
2787					} else if (keytype == CKK_AES) {
2788						keys[n].keyalg = KMF_AES;
2789						keys[n].keyclass =
2790						    KMF_SYMMETRIC;
2791					} else if (keytype == CKK_RC4) {
2792						keys[n].keyalg = KMF_RC4;
2793						keys[n].keyclass =
2794						    KMF_SYMMETRIC;
2795					} else if (keytype == CKK_DES) {
2796						keys[n].keyalg = KMF_DES;
2797						keys[n].keyclass =
2798						    KMF_SYMMETRIC;
2799					} else if (keytype == CKK_DES3) {
2800						keys[n].keyalg = KMF_DES3;
2801						keys[n].keyclass =
2802						    KMF_SYMMETRIC;
2803					} else if (keytype ==
2804					    CKK_GENERIC_SECRET) {
2805						keys[n].keyalg =
2806						    KMF_GENERIC_SECRET;
2807						keys[n].keyclass =
2808						    KMF_SYMMETRIC;
2809					}
2810
2811				}
2812				n++;
2813			} else {
2814				break;
2815			}
2816		}
2817		ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2818
2819		/* "numkeys" indicates the number that were actually found */
2820		*numkeys = n;
2821	}
2822
2823	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
2824		if ((rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
2825		    numattr, (void *)&format, NULL)) == KMF_OK) {
2826			if (format == KMF_FORMAT_RAWKEY ||
2827			    format == KMF_FORMAT_PEM) {
2828				/* Convert keys to "rawkey" format */
2829				for (i = 0; i < (*numkeys); i++) {
2830					KMF_RAW_KEY_DATA *rkey = NULL;
2831					rv = keyObj2RawKey(handle, &keys[i],
2832					    &rkey);
2833					if (rv == KMF_OK) {
2834						keys[i].keyp = rkey;
2835						keys[i].israw = TRUE;
2836					} else {
2837						break;
2838					}
2839				}
2840			}
2841		} else {
2842			rv = KMF_OK; /* format is optional */
2843		}
2844	}
2845
2846end:
2847	if (ckrv != CKR_OK) {
2848		SET_ERROR(kmfh, ckrv);
2849		/* Report authentication failures to the caller */
2850		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2851		    ckrv == CKR_PIN_INCORRECT ||
2852		    ckrv == CKR_PIN_INVALID ||
2853		    ckrv == CKR_PIN_EXPIRED ||
2854		    ckrv == CKR_PIN_LOCKED ||
2855		    ckrv == CKR_SESSION_READ_ONLY)
2856			rv = KMF_ERR_AUTH_FAILED;
2857		else
2858			rv = KMF_ERR_INTERNAL;
2859	} else if ((*numkeys) == 0) {
2860		rv = KMF_ERR_KEY_NOT_FOUND;
2861	}
2862
2863	return (rv);
2864}
2865
2866static char *
2867convertDate(char *fulldate)
2868{
2869	struct tm tms;
2870	char newtime[9];
2871
2872	(void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2873
2874	if (tms.tm_year < 69)
2875		tms.tm_year += 100;
2876
2877	(void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2878
2879	newtime[8] = 0;
2880
2881	/* memory returned must be freed by the caller */
2882	return ((char *)strdup(newtime));
2883}
2884
2885static KMF_RETURN
2886store_raw_key(KMF_HANDLE_T handle,
2887	KMF_ATTRIBUTE *attrlist, int numattr,
2888	KMF_RAW_KEY_DATA *rawkey)
2889{
2890	KMF_RETURN rv = KMF_OK;
2891	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2892	int i;
2893	CK_RV		ckrv = CKR_OK;
2894	CK_ATTRIBUTE	templ[32];
2895	CK_OBJECT_HANDLE keyobj;
2896	CK_KEY_TYPE	keytype;
2897	CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2898	CK_BBOOL	cktrue = TRUE;
2899	CK_DATE		startdate, enddate;
2900	KMF_DATA	id = {NULL, 0};
2901	KMF_DATA	subject = {NULL, 0};
2902	KMF_X509EXT_KEY_USAGE kuext;
2903	KMF_X509_CERTIFICATE *x509 = NULL;
2904	CK_BBOOL	kufound = B_FALSE;
2905	KMF_DATA	*cert = NULL;
2906	char		*notbefore = NULL, *start = NULL;
2907	char		*notafter = NULL, *end = NULL;
2908	char		*keylabel = NULL;
2909
2910	if (kmfh == NULL)
2911		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2912
2913	if (kmfh->pk11handle == CK_INVALID_HANDLE)
2914		return (KMF_ERR_NO_TOKEN_SELECTED);
2915
2916	if (rawkey->keytype == KMF_RSA)
2917		keytype = CKK_RSA;
2918	else if (rawkey->keytype == KMF_DSA)
2919		keytype = CKK_DSA;
2920	else
2921		return (KMF_ERR_BAD_PARAMETER);
2922
2923	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2924	/*
2925	 * If the caller did not specify a label, see if the raw key
2926	 * came with one (possible if it came from a PKCS#12 file).
2927	 */
2928	if (keylabel == NULL) {
2929		keylabel = rawkey->label;
2930	}
2931
2932	i = 0;
2933	SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2934	SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2935	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2936	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2937	SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
2938
2939	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2940	if (cert != NULL) {
2941		id.Data = NULL;
2942		id.Length = 0;
2943		rv = kmf_get_cert_id_data(cert, &id);
2944		if (rv != KMF_OK) {
2945			goto cleanup;
2946		}
2947
2948		rv = DerDecodeSignedCertificate((const KMF_DATA *)cert, &x509);
2949		if (rv != KMF_OK) {
2950			goto cleanup;
2951		}
2952
2953		rv = DerEncodeName(&x509->certificate.subject, &subject);
2954		if (rv != KMF_OK) {
2955			goto cleanup;
2956		}
2957		SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length);
2958		i++;
2959
2960		rv = kmf_get_cert_start_date_str(handle, cert, &notbefore);
2961		if (rv != KMF_OK) {
2962			goto cleanup;
2963		}
2964		start = convertDate(notbefore);
2965		free(notbefore);
2966
2967		rv = kmf_get_cert_end_date_str(handle, cert, &notafter);
2968		if (rv != KMF_OK) {
2969			goto cleanup;
2970		}
2971		end = convertDate(notafter);
2972		free(notafter);
2973		if (id.Data != NULL && id.Data != NULL && id.Length > 0) {
2974			SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2975			i++;
2976		}
2977		if (start != NULL) {
2978			/*
2979			 * This makes some potentially dangerous assumptions:
2980			 *  1. that the startdate in the parameter block is
2981			 * properly formatted as YYYYMMDD
2982			 *  2. That the CK_DATE structure is always the same.
2983			 */
2984			(void) memcpy(&startdate, start, sizeof (CK_DATE));
2985			SETATTR(templ, i, CKA_START_DATE, &startdate,
2986			    sizeof (startdate));
2987			i++;
2988		}
2989		if (end != NULL) {
2990			(void) memcpy(&enddate, end, sizeof (CK_DATE));
2991			SETATTR(templ, i, CKA_END_DATE, &enddate,
2992			    sizeof (enddate));
2993			i++;
2994		}
2995
2996		if ((rv = kmf_get_cert_ku(cert, &kuext)) != KMF_OK &&
2997		    rv != KMF_ERR_EXTENSION_NOT_FOUND)
2998			goto cleanup;
2999
3000		kufound = (rv == KMF_OK);
3001		rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND */
3002	}
3003
3004	/*
3005	 * Only set the KeyUsage stuff if the KU extension was present.
3006	 */
3007	if (kufound) {
3008		CK_BBOOL	condition;
3009
3010		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
3011		    B_TRUE : B_FALSE;
3012		SETATTR(templ, i, CKA_UNWRAP, &condition, sizeof (CK_BBOOL));
3013		i++;
3014		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
3015		    B_TRUE : B_FALSE;
3016		SETATTR(templ, i, CKA_DECRYPT, &condition, sizeof (CK_BBOOL));
3017		i++;
3018		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3019		    B_TRUE : B_FALSE;
3020		SETATTR(templ, i, CKA_SIGN, &condition,	sizeof (CK_BBOOL));
3021		i++;
3022		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3023		    B_TRUE : B_FALSE;
3024		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
3025		    sizeof (CK_BBOOL));
3026		i++;
3027
3028	}
3029
3030	if (keylabel != NULL) {
3031		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3032		i++;
3033	}
3034	if (id.Data == NULL && rawkey->id.Data != NULL) {
3035		SETATTR(templ, i, CKA_ID, rawkey->id.Data,
3036		    rawkey->id.Length);
3037		i++;
3038	}
3039	if (keytype == CKK_RSA) {
3040		SETATTR(templ, i, CKA_MODULUS,
3041		    rawkey->rawdata.rsa.mod.val,
3042		    rawkey->rawdata.rsa.mod.len);
3043		i++;
3044		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
3045		    rawkey->rawdata.rsa.pubexp.val,
3046		    rawkey->rawdata.rsa.pubexp.len);
3047		i++;
3048		if (rawkey->rawdata.rsa.priexp.val != NULL) {
3049			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
3050			    rawkey->rawdata.rsa.priexp.val,
3051			    rawkey->rawdata.rsa.priexp.len);
3052			i++;
3053		}
3054		if (rawkey->rawdata.rsa.prime1.val != NULL) {
3055			SETATTR(templ, i, CKA_PRIME_1,
3056			    rawkey->rawdata.rsa.prime1.val,
3057			    rawkey->rawdata.rsa.prime1.len);
3058			i++;
3059		}
3060		if (rawkey->rawdata.rsa.prime2.val != NULL) {
3061			SETATTR(templ, i, CKA_PRIME_2,
3062			    rawkey->rawdata.rsa.prime2.val,
3063			    rawkey->rawdata.rsa.prime2.len);
3064			i++;
3065		}
3066		if (rawkey->rawdata.rsa.exp1.val != NULL) {
3067			SETATTR(templ, i, CKA_EXPONENT_1,
3068			    rawkey->rawdata.rsa.exp1.val,
3069			    rawkey->rawdata.rsa.exp1.len);
3070			i++;
3071		}
3072		if (rawkey->rawdata.rsa.exp2.val != NULL) {
3073			SETATTR(templ, i, CKA_EXPONENT_2,
3074			    rawkey->rawdata.rsa.exp2.val,
3075			    rawkey->rawdata.rsa.exp2.len);
3076			i++;
3077		}
3078		if (rawkey->rawdata.rsa.coef.val != NULL) {
3079			SETATTR(templ, i, CKA_COEFFICIENT,
3080			    rawkey->rawdata.rsa.coef.val,
3081			    rawkey->rawdata.rsa.coef.len);
3082			i++;
3083		}
3084	} else {
3085		SETATTR(templ, i, CKA_PRIME,
3086		    rawkey->rawdata.dsa.prime.val,
3087		    rawkey->rawdata.dsa.prime.len);
3088		i++;
3089		SETATTR(templ, i, CKA_SUBPRIME,
3090		    rawkey->rawdata.dsa.subprime.val,
3091		    rawkey->rawdata.dsa.subprime.len);
3092		i++;
3093		SETATTR(templ, i, CKA_BASE,
3094		    rawkey->rawdata.dsa.base.val,
3095		    rawkey->rawdata.dsa.base.len);
3096		i++;
3097		SETATTR(templ, i, CKA_VALUE,
3098		    rawkey->rawdata.dsa.value.val,
3099		    rawkey->rawdata.dsa.value.len);
3100		i++;
3101	}
3102
3103	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
3104	if (ckrv != CKR_OK) {
3105		SET_ERROR(kmfh, ckrv);
3106
3107		/* Report authentication failures to the caller */
3108		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3109		    ckrv == CKR_PIN_INCORRECT ||
3110		    ckrv == CKR_PIN_INVALID ||
3111		    ckrv == CKR_PIN_EXPIRED ||
3112		    ckrv == CKR_PIN_LOCKED ||
3113		    ckrv == CKR_SESSION_READ_ONLY)
3114			rv = KMF_ERR_AUTH_FAILED;
3115		else
3116			rv = KMF_ERR_INTERNAL;
3117	}
3118cleanup:
3119	if (start != NULL)
3120		free(start);
3121	if (end != NULL)
3122		free(end);
3123	kmf_free_data(&id);
3124	kmf_free_data(&subject);
3125	kmf_free_signed_cert(x509);
3126	free(x509);
3127
3128	return (rv);
3129}
3130
3131KMF_RETURN
3132KMFPK11_CreateSymKey(KMF_HANDLE_T handle,
3133    int numattr, KMF_ATTRIBUTE *attrlist)
3134{
3135	KMF_RETURN		rv = KMF_OK;
3136	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3137	CK_RV			ckrv;
3138	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3139	CK_OBJECT_HANDLE	keyhandle;
3140	CK_MECHANISM		keyGenMech;
3141	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3142	CK_ULONG		secKeyType;
3143	CK_ULONG		secKeyLen;	/* for RC4 and AES */
3144	CK_BBOOL		true = TRUE;
3145	CK_BBOOL		false = FALSE;
3146	CK_ATTRIBUTE		templ[15];
3147	CK_BYTE			*keydata = NULL;
3148	int			i = 0;
3149	KMF_KEY_HANDLE		*symkey;
3150	KMF_KEY_ALG		keytype;
3151	uint32_t		keylen = 0;
3152	uint32_t		attrkeylen = 0;
3153	uint32_t		keylen_size = sizeof (uint32_t);
3154	char			*keylabel = NULL;
3155	KMF_CREDENTIAL		*cred = NULL;
3156	uint32_t		is_sensitive = B_FALSE;
3157	uint32_t		is_not_extractable = B_FALSE;
3158
3159	if (kmfh == NULL)
3160		return (KMF_ERR_UNINITIALIZED);
3161
3162	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3163		return (KMF_ERR_NO_TOKEN_SELECTED);
3164
3165	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3166	if (symkey == NULL)
3167		return (KMF_ERR_BAD_PARAMETER);
3168
3169	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
3170	    (void *)&keytype, NULL);
3171	if (rv != KMF_OK)
3172		return (KMF_ERR_BAD_PARAMETER);
3173
3174	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3175	if (keylabel == NULL)
3176		return (KMF_ERR_BAD_PARAMETER);
3177
3178	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3179	    (void *)&is_sensitive, NULL);
3180	if (rv != KMF_OK)
3181		return (KMF_ERR_BAD_PARAMETER);
3182
3183	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3184	    (void *)&is_not_extractable, NULL);
3185	if (rv != KMF_OK)
3186		return (KMF_ERR_BAD_PARAMETER);
3187
3188	/*
3189	 * For AES, RC4, DES and 3DES, call C_GenerateKey() to create a key.
3190	 *
3191	 * For a generic secret key, because it may not be supported in
3192	 * C_GenerateKey() for some PKCS11 providers, we will handle it
3193	 * differently.
3194	 */
3195	if (keytype == KMF_GENERIC_SECRET) {
3196		rv = create_generic_secret_key(handle, numattr,
3197		    attrlist, &keyhandle);
3198		if (rv != KMF_OK)
3199			goto out;
3200		else
3201			goto setup;
3202	}
3203
3204	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3205	    NULL, &attrkeylen);
3206	if (rv == KMF_OK && attrkeylen > 0) {
3207		keydata = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3208		    numattr);
3209	} else {
3210		keydata = NULL;
3211		attrkeylen = 0;
3212		rv = KMF_OK;
3213	}
3214	if (keydata != NULL) {
3215		if (keytype == KMF_DES && attrkeylen != 8) {
3216			rv = KMF_ERR_BAD_KEY_SIZE;
3217			goto out;
3218		}
3219		if (keytype == KMF_DES3 && attrkeylen != 24) {
3220			rv = KMF_ERR_BAD_KEY_SIZE;
3221			goto out;
3222		}
3223		/*
3224		 * This may override what the user gave on the
3225		 * command line.
3226		 */
3227		keylen = attrkeylen * 8; /* bytes to bits */
3228	} else {
3229		/*
3230		 * If keydata was not given, key length must be
3231		 * provided.
3232		 */
3233		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3234		    &keylen, &keylen_size);
3235		if (rv == KMF_ERR_ATTR_NOT_FOUND &&
3236		    (keytype == KMF_DES || keytype == KMF_DES3))
3237			/* keylength is not required for DES and 3DES */
3238			rv = KMF_OK;
3239		if (rv != KMF_OK)
3240			return (KMF_ERR_BAD_PARAMETER);
3241	}
3242
3243	if ((keylen % 8) != 0) {
3244		return (KMF_ERR_BAD_KEY_SIZE);
3245	}
3246	secKeyLen = keylen / 8;  /* in bytes for RC4/AES */
3247
3248	/*
3249	 * Only set CKA_VALUE_LEN if the key data was not given and
3250	 * we are creating an RC4 or AES key.
3251	 */
3252	if (keydata == NULL &&
3253	    (keytype == KMF_AES || keytype == KMF_RC4)) {
3254		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
3255		    sizeof (secKeyLen));
3256		i++;
3257	}
3258
3259	/* Other keytypes */
3260	keyGenMech.pParameter = NULL_PTR;
3261	keyGenMech.ulParameterLen = 0;
3262	switch (keytype) {
3263		case KMF_AES:
3264			keyGenMech.mechanism = CKM_AES_KEY_GEN;
3265			secKeyType = CKK_AES;
3266			break;
3267		case KMF_RC4:
3268			keyGenMech.mechanism = CKM_RC4_KEY_GEN;
3269			secKeyType = CKK_RC4;
3270			break;
3271		case KMF_DES:
3272			keyGenMech.mechanism = CKM_DES_KEY_GEN;
3273			secKeyType = CKK_DES;
3274			break;
3275		case KMF_DES3:
3276			keyGenMech.mechanism = CKM_DES3_KEY_GEN;
3277			secKeyType = CKK_DES3;
3278			break;
3279		default:
3280			return (KMF_ERR_BAD_KEY_TYPE);
3281	}
3282	if (keydata != NULL) {
3283		SETATTR(templ, i, CKA_VALUE, keydata, secKeyLen);
3284		i++;
3285	}
3286	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3287	i++;
3288	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3289	i++;
3290
3291	if (keylabel != NULL) {
3292		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3293		i++;
3294	}
3295
3296	if (is_sensitive == B_TRUE) {
3297		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3298	} else {
3299		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3300	}
3301	i++;
3302
3303	if (is_not_extractable == B_TRUE) {
3304		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3305	} else {
3306		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3307	}
3308	i++;
3309
3310	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3311	i++;
3312	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3313	i++;
3314	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
3315	i++;
3316	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
3317	i++;
3318	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3319	i++;
3320	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
3321	i++;
3322
3323	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3324	if (cred == NULL)
3325		return (KMF_ERR_BAD_PARAMETER);
3326
3327	rv = pk11_authenticate(handle, cred);
3328	if (rv != KMF_OK) {
3329		return (rv);
3330	}
3331
3332	/* If the key data was given, use C_CreateObject */
3333	if (keydata != NULL) {
3334		ckrv = C_CreateObject(hSession, templ, i, &keyhandle);
3335	} else {
3336		ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i,
3337		    &keyhandle);
3338	}
3339	if (ckrv != CKR_OK) {
3340		SET_ERROR(kmfh, ckrv);
3341		rv = KMF_ERR_KEYGEN_FAILED;
3342		goto out;
3343	}
3344
3345setup:
3346	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
3347	symkey->keyalg = keytype;
3348	symkey->keyclass = KMF_SYMMETRIC;
3349	symkey->israw = FALSE;
3350	symkey->keyp = (void *)keyhandle;
3351
3352out:
3353	return (rv);
3354}
3355
3356KMF_RETURN
3357KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
3358    KMF_RAW_SYM_KEY *rkey)
3359{
3360	KMF_RETURN		rv = KMF_OK;
3361	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3362
3363	if (kmfh == NULL)
3364		return (KMF_ERR_UNINITIALIZED);
3365
3366	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3367		return (KMF_ERR_NO_TOKEN_SELECTED);
3368
3369	if (symkey == NULL || rkey == NULL)
3370		return (KMF_ERR_BAD_PARAMETER);
3371	else if (symkey->keyclass != KMF_SYMMETRIC)
3372		return (KMF_ERR_BAD_KEY_CLASS);
3373
3374	/*
3375	 * If the key is already in "raw" format, copy the data
3376	 * to the new record if possible.
3377	 */
3378	if (symkey->israw) {
3379		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
3380
3381		if (rawkey == NULL)
3382			return (KMF_ERR_BAD_KEYHANDLE);
3383		if (rawkey->sensitive)
3384			return (KMF_ERR_SENSITIVE_KEY);
3385		if (rawkey->not_extractable)
3386			return (KMF_ERR_UNEXTRACTABLE_KEY);
3387
3388		if (rawkey->rawdata.sym.keydata.val == NULL ||
3389		    rawkey->rawdata.sym.keydata.len == 0)
3390			return (KMF_ERR_GETKEYVALUE_FAILED);
3391
3392		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
3393		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
3394			return (KMF_ERR_MEMORY);
3395		(void) memcpy(rkey->keydata.val,
3396		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
3397	} else {
3398		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
3399	}
3400
3401	return (rv);
3402}
3403
3404KMF_RETURN
3405KMFPK11_SetTokenPin(KMF_HANDLE_T handle,
3406	int numattr, KMF_ATTRIBUTE *attrlist)
3407{
3408	KMF_RETURN	ret = KMF_OK;
3409	CK_RV		rv = CKR_OK;
3410	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3411	CK_SESSION_HANDLE	session = NULL;
3412	KMF_CREDENTIAL	*oldcred;
3413	KMF_CREDENTIAL	*newcred;
3414	CK_SLOT_ID	slotid;
3415
3416	if (handle == NULL || attrlist == NULL || numattr == 0)
3417		return (KMF_ERR_BAD_PARAMETER);
3418
3419	oldcred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3420	if (oldcred == NULL)
3421		return (KMF_ERR_BAD_PARAMETER);
3422
3423	newcred = kmf_get_attr_ptr(KMF_NEWPIN_ATTR, attrlist, numattr);
3424	if (newcred == NULL)
3425		return (KMF_ERR_BAD_PARAMETER);
3426
3427	rv = kmf_get_attr(KMF_SLOT_ID_ATTR, attrlist, numattr,
3428	    (void *)&slotid, NULL);
3429	if (rv != KMF_OK) {
3430		char *tokenlabel = NULL;
3431		/*
3432		 * If a slot wasn't given, the user must pass
3433		 * a token label so we can find the slot here.
3434		 */
3435		tokenlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
3436		    numattr);
3437		if (tokenlabel == NULL)
3438			return (KMF_ERR_BAD_PARAMETER);
3439
3440		rv = kmf_pk11_token_lookup(handle, tokenlabel, &slotid);
3441		if (rv != KMF_OK)
3442			return (rv);
3443	}
3444
3445	rv = C_OpenSession(slotid, CKF_SERIAL_SESSION | CKF_RW_SESSION,
3446	    NULL, NULL, &session);
3447	if (rv != CKR_OK) {
3448		SET_ERROR(kmfh, rv);
3449		ret = KMF_ERR_UNINITIALIZED;
3450		goto end;
3451	}
3452
3453	rv = C_SetPIN(session,
3454	    (CK_BYTE *)oldcred->cred, oldcred->credlen,
3455	    (CK_BYTE *)newcred->cred, newcred->credlen);
3456
3457	if (rv != CKR_OK) {
3458		SET_ERROR(kmfh, rv);
3459		if (rv == CKR_PIN_INCORRECT ||
3460		    rv == CKR_PIN_INVALID ||
3461		    rv == CKR_PIN_EXPIRED ||
3462		    rv == CKR_PIN_LOCKED)
3463			ret = KMF_ERR_AUTH_FAILED;
3464		else
3465			ret = KMF_ERR_INTERNAL;
3466	}
3467end:
3468	if (session != NULL)
3469		(void) C_CloseSession(session);
3470	return (ret);
3471}
3472
3473static KMF_RETURN
3474create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
3475	CK_FLAGS wanted_flags)
3476{
3477	CK_RV rv;
3478	KMF_RETURN kmf_rv = KMF_OK;
3479	CK_SLOT_ID_PTR pSlotList;
3480	CK_ULONG pulCount;
3481	CK_MECHANISM_INFO info;
3482	int i;
3483
3484	rv = C_Initialize(NULL);
3485	if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
3486		kmf_rv = KMF_ERR_UNINITIALIZED;
3487		goto out;
3488	}
3489
3490	rv = C_GetSlotList(0, NULL, &pulCount);
3491	if (rv != CKR_OK) {
3492		kmf_rv = KMF_ERR_UNINITIALIZED;
3493		goto out;
3494	}
3495
3496	pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
3497	if (pSlotList == NULL) {
3498		kmf_rv = KMF_ERR_MEMORY;
3499		goto out;
3500	}
3501
3502	rv = C_GetSlotList(0, pSlotList, &pulCount);
3503	if (rv != CKR_OK) {
3504		kmf_rv = KMF_ERR_UNINITIALIZED;
3505		goto out;
3506	}
3507
3508	for (i = 0; i < pulCount; i++) {
3509		rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
3510		if (rv == CKR_OK && (info.flags & wanted_flags))
3511			break;
3512	}
3513	if (i < pulCount) {
3514		rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
3515		    NULL, NULL, sessionp);
3516
3517		if (rv != CKR_OK) {
3518			kmf_rv = KMF_ERR_UNINITIALIZED;
3519		}
3520	} else {
3521		kmf_rv = KMF_ERR_UNINITIALIZED;
3522	}
3523
3524out:
3525	if (pSlotList != NULL)
3526		free(pSlotList);
3527	return (kmf_rv);
3528
3529}
3530static KMF_RETURN
3531verify_data(KMF_HANDLE_T handle,
3532	KMF_ALGORITHM_INDEX AlgorithmId,
3533	KMF_X509_SPKI *keyp,
3534	KMF_DATA *data,
3535	KMF_DATA *signed_data)
3536{
3537	KMF_RETURN ret;
3538	PKCS_ALGORITHM_MAP *pAlgMap = NULL;
3539	CK_RV ckRv;
3540	CK_MECHANISM ckMechanism;
3541	CK_OBJECT_HANDLE ckKeyHandle;
3542	KMF_BOOL	bTempKey;
3543	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3544	CK_SESSION_HANDLE	ckSession = NULL;
3545
3546	if (AlgorithmId == KMF_ALGID_NONE)
3547		return (KMF_ERR_BAD_ALGORITHM);
3548
3549	pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
3550	    AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
3551
3552	if (!pAlgMap)
3553		return (KMF_ERR_BAD_ALGORITHM);
3554
3555	ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
3556	    CKF_VERIFY);
3557	if (ret != KMF_OK)
3558		return (ret);
3559
3560	/* Fetch the verifying key */
3561	ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
3562	    pAlgMap->key_type, &ckKeyHandle, &bTempKey);
3563
3564	if (ret != KMF_OK) {
3565		return (ret);
3566	}
3567
3568	ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
3569	ckMechanism.pParameter = NULL;
3570	ckMechanism.ulParameterLen = 0;
3571
3572	ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
3573	if (ckRv != CKR_OK) {
3574		if (bTempKey)
3575			(void) C_DestroyObject(ckSession, ckKeyHandle);
3576		SET_ERROR(kmfh, ckRv);
3577		ret = KMF_ERR_INTERNAL;
3578		goto cleanup;
3579	}
3580
3581	ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data,
3582	    (CK_ULONG)data->Length, (CK_BYTE *)signed_data->Data,
3583	    (CK_ULONG)signed_data->Length);
3584
3585	if (ckRv != CKR_OK) {
3586		SET_ERROR(kmfh, ckRv);
3587		ret = KMF_ERR_INTERNAL;
3588	}
3589
3590cleanup:
3591	if (bTempKey)
3592		(void) C_DestroyObject(ckSession, ckKeyHandle);
3593
3594	(void) C_CloseSession(ckSession);
3595
3596	return (ret);
3597}
3598
3599KMF_RETURN
3600KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle,
3601	KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
3602	KMF_DATA *insig, KMF_DATA *SignerCertData)
3603{
3604	KMF_RETURN ret = KMF_OK;
3605	KMF_X509_CERTIFICATE *SignerCert = NULL;
3606	KMF_X509_SPKI *pubkey;
3607
3608	if (handle == NULL || indata == NULL ||
3609	    indata->Data == NULL || indata->Length == 0 ||
3610	    insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
3611	    SignerCertData == NULL || SignerCertData->Data == NULL ||
3612	    SignerCertData->Length == 0)
3613		return (KMF_ERR_BAD_PARAMETER);
3614
3615	/* Decode the signer cert so we can get the SPKI data */
3616	ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
3617	if (ret != KMF_OK)
3618		goto cleanup;
3619
3620	/* Get the public key info from the signer certificate */
3621	pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
3622
3623	/* If no algorithm specified, use the certs signature algorithm */
3624	if (algid == KMF_ALGID_NONE) {
3625		algid = x509_algoid_to_algid(CERT_ALG_OID(SignerCert));
3626	}
3627
3628	if (algid == KMF_ALGID_NONE) {
3629		ret = KMF_ERR_BAD_ALGORITHM;
3630	} else {
3631		ret = verify_data(handle, algid, pubkey, indata, insig);
3632	}
3633
3634cleanup:
3635	if (SignerCert) {
3636		kmf_free_signed_cert(SignerCert);
3637		free(SignerCert);
3638	}
3639
3640	return (ret);
3641}
3642
3643static KMF_RETURN
3644create_generic_secret_key(KMF_HANDLE_T handle,
3645	int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key)
3646{
3647	KMF_RETURN		rv = KMF_OK;
3648	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3649	CK_RV			ckrv;
3650	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3651	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3652	CK_ULONG		secKeyType = CKK_GENERIC_SECRET;
3653	CK_ULONG		secKeyLen;
3654	CK_BBOOL		true = TRUE;
3655	CK_BBOOL		false = FALSE;
3656	CK_ATTRIBUTE		templ[15];
3657	int			i;
3658	int			random_fd = -1;
3659	int			nread;
3660	int			freebuf = 0;
3661	char			*buf = NULL;
3662	uint32_t		keylen = 0, attrkeylen = 0;
3663	char			*keylabel = NULL;
3664	KMF_CREDENTIAL		*cred;
3665	uint32_t is_sensitive, is_not_extractable;
3666
3667	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3668	if (keylabel == NULL)
3669		return (KMF_ERR_BAD_PARAMETER);
3670
3671	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3672	if (cred == NULL)
3673		return (KMF_ERR_BAD_PARAMETER);
3674
3675	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3676	    (void *)&is_sensitive, NULL);
3677	if (rv != KMF_OK)
3678		return (KMF_ERR_BAD_PARAMETER);
3679
3680	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3681	    (void *)&is_not_extractable, NULL);
3682	if (rv != KMF_OK)
3683		return (KMF_ERR_BAD_PARAMETER);
3684
3685	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3686	    NULL, &attrkeylen);
3687	if (rv == KMF_OK && attrkeylen > 0) {
3688		buf = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3689		    numattr);
3690		secKeyLen = attrkeylen;
3691	} else {
3692		buf = NULL;
3693		rv = KMF_OK;
3694	}
3695	if (buf == NULL) {
3696		/*
3697		 * If the key data was not given, key length must
3698		 * be provided.
3699		 */
3700		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3701		    &keylen, NULL);
3702		if (rv != KMF_OK)
3703			return (KMF_ERR_BAD_PARAMETER);
3704
3705		/*
3706		 * Check the key size.
3707		 */
3708		if ((keylen % 8) != 0) {
3709			return (KMF_ERR_BAD_KEY_SIZE);
3710		} else {
3711			secKeyLen = keylen/8;  /* in bytes */
3712		}
3713
3714		/*
3715		 * Generate a random number with the key size first.
3716		 */
3717		buf = malloc(secKeyLen);
3718		if (buf == NULL)
3719			return (KMF_ERR_MEMORY);
3720
3721		freebuf = 1;
3722		while ((random_fd = open(DEV_RANDOM, O_RDONLY)) < 0) {
3723			if (errno != EINTR)
3724				break;
3725		}
3726
3727		if (random_fd < 0) {
3728			rv = KMF_ERR_KEYGEN_FAILED;
3729			goto out;
3730		}
3731
3732		nread = read(random_fd, buf, secKeyLen);
3733		if (nread <= 0 || nread != secKeyLen) {
3734			rv = KMF_ERR_KEYGEN_FAILED;
3735			goto out;
3736		}
3737	}
3738
3739	/*
3740	 * Authenticate into the token and call C_CreateObject to generate
3741	 * a generic secret token key.
3742	 */
3743	rv = pk11_authenticate(handle, cred);
3744	if (rv != KMF_OK) {
3745		goto out;
3746	}
3747
3748	i = 0;
3749	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3750	i++;
3751	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3752	i++;
3753	SETATTR(templ, i, CKA_VALUE, buf, secKeyLen);
3754	i++;
3755
3756	if (keylabel != NULL) {
3757		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3758		i++;
3759	}
3760
3761	if (is_sensitive == B_TRUE) {
3762		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3763	} else {
3764		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3765	}
3766	i++;
3767
3768	if (is_not_extractable == B_TRUE) {
3769		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3770	} else {
3771		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3772	}
3773	i++;
3774
3775	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3776	i++;
3777	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3778	i++;
3779	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3780	i++;
3781
3782	ckrv = C_CreateObject(hSession, templ, i, key);
3783	if (ckrv != CKR_OK) {
3784		SET_ERROR(kmfh, ckrv);
3785		rv = KMF_ERR_KEYGEN_FAILED;
3786	}
3787
3788out:
3789	if (buf != NULL && freebuf)
3790		free(buf);
3791
3792	if (random_fd != -1)
3793		(void) close(random_fd);
3794
3795	return (rv);
3796}
3797
3798KMF_RETURN
3799KMFPK11_StoreKey(KMF_HANDLE_T handle,
3800	int numattr,
3801	KMF_ATTRIBUTE *attlist)
3802{
3803	KMF_RETURN rv = KMF_OK;
3804	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3805	KMF_CREDENTIAL cred = {NULL, 0};
3806	KMF_KEY_HANDLE *key;
3807	KMF_RAW_KEY_DATA *rawkey = NULL;
3808	CK_BBOOL btrue = TRUE;
3809	CK_ATTRIBUTE tokenattr[1];
3810	CK_OBJECT_HANDLE newobj;
3811	CK_RV ckrv;
3812
3813	if (kmfh == NULL)
3814		return (KMF_ERR_UNINITIALIZED);
3815
3816	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3817		return (KMF_ERR_NO_TOKEN_SELECTED);
3818
3819	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attlist, numattr,
3820	    (void *)&cred, NULL);
3821	if (rv != KMF_OK)
3822		return (KMF_ERR_BAD_PARAMETER);
3823
3824	rv = pk11_authenticate(handle, &cred);
3825	if (rv != KMF_OK)
3826		return (rv);
3827
3828	key = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
3829	if (key == NULL) {
3830		key = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist,
3831		    numattr);
3832		if (key == NULL)
3833			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attlist,
3834			    numattr);
3835	}
3836	if (key == NULL && rawkey == NULL)
3837		return (KMF_ERR_ATTR_NOT_FOUND);
3838
3839	if (rawkey != NULL) {
3840		rv = store_raw_key(handle, attlist, numattr, rawkey);
3841	} else if (key && key->kstype == KMF_KEYSTORE_PK11TOKEN) {
3842
3843		SETATTR(tokenattr, 0, CKA_TOKEN, &btrue, sizeof (btrue));
3844		/* Copy the key object to the token */
3845		ckrv = C_CopyObject(kmfh->pk11handle,
3846		    (CK_OBJECT_HANDLE)key->keyp, tokenattr, 1, &newobj);
3847		if (ckrv != CKR_OK)  {
3848			SET_ERROR(kmfh, ckrv);
3849			return (KMF_ERR_INTERNAL);
3850		}
3851
3852		/* Replace the object handle with the new token-based one */
3853		ckrv = C_DestroyObject(kmfh->pk11handle,
3854		    (CK_OBJECT_HANDLE)key->keyp);
3855		if (ckrv != CKR_OK)  {
3856			SET_ERROR(kmfh, ckrv);
3857			return (KMF_ERR_INTERNAL);
3858		}
3859		key->keyp = (void *)newobj;
3860	} else {
3861		rv = KMF_ERR_BAD_PARAMETER;
3862	}
3863
3864	return (rv);
3865}
3866
3867
3868KMF_RETURN
3869KMFPK11_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3870{
3871	KMF_RETURN rv = KMF_OK;
3872	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3873	KMF_CREDENTIAL *cred = NULL;
3874	KMF_CREDENTIAL *p12cred = NULL;
3875	char *filename = NULL;
3876	KMF_X509_DER_CERT *certlist = NULL;
3877	KMF_KEY_HANDLE *keylist = NULL;
3878	uint32_t numcerts;
3879	uint32_t numkeys;
3880	char *certlabel = NULL;
3881	char *issuer = NULL;
3882	char *subject = NULL;
3883	KMF_BIGINT *serial = NULL;
3884	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
3885	KMF_ATTRIBUTE fc_attrlist[16];
3886	int i;
3887
3888	if (kmfh == NULL)
3889		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
3890
3891	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3892		return (KMF_ERR_NO_TOKEN_SELECTED);
3893
3894	/* First get the required attributes */
3895	cred =  kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3896	if (cred == NULL)
3897		return (KMF_ERR_BAD_PARAMETER);
3898
3899	p12cred =  kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3900	if (p12cred == NULL)
3901		return (KMF_ERR_BAD_PARAMETER);
3902
3903	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3904	    numattr);
3905	if (filename == NULL)
3906		return (KMF_ERR_BAD_PARAMETER);
3907
3908	/* Find all the certificates that match the searching criteria */
3909	i = 0;
3910	kmf_set_attr_at_index(fc_attrlist, i,
3911	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
3912	i++;
3913
3914	kmf_set_attr_at_index(fc_attrlist, i,
3915	    KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
3916	i++;
3917
3918	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
3919	if (certlabel != NULL) {
3920		kmf_set_attr_at_index(fc_attrlist, i,
3921		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
3922		i++;
3923	}
3924
3925	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
3926	if (issuer != NULL) {
3927		kmf_set_attr_at_index(fc_attrlist, i,
3928		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
3929		i++;
3930	}
3931
3932	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
3933	if (subject != NULL) {
3934		kmf_set_attr_at_index(fc_attrlist, i,
3935		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
3936		i++;
3937	}
3938
3939	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
3940	if (serial != NULL) {
3941		kmf_set_attr_at_index(fc_attrlist, i,
3942		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
3943		i++;
3944	}
3945
3946	rv = KMFPK11_FindCert(handle, i, fc_attrlist);
3947
3948	if (rv == KMF_OK && numcerts > 0) {
3949		certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
3950		    sizeof (KMF_X509_DER_CERT));
3951		if (certlist == NULL)
3952			return (KMF_ERR_MEMORY);
3953
3954		(void) memset(certlist, 0, numcerts *
3955		    sizeof (KMF_X509_DER_CERT));
3956
3957		kmf_set_attr_at_index(fc_attrlist, i, KMF_X509_DER_CERT_ATTR,
3958		    certlist, sizeof (KMF_X509_DER_CERT));
3959		i++;
3960
3961		rv = kmf_find_cert(handle, i, fc_attrlist);
3962		if (rv != KMF_OK) {
3963			free(certlist);
3964			return (rv);
3965		}
3966	} else {
3967		return (rv);
3968	}
3969
3970	/* For each certificate, find the matching private key */
3971	numkeys = 0;
3972	for (i = 0; i < numcerts; i++) {
3973		KMF_ATTRIBUTE fk_attrlist[16];
3974		int j = 0;
3975		KMF_KEY_HANDLE newkey;
3976		KMF_ENCODE_FORMAT format = KMF_FORMAT_RAWKEY;
3977
3978		kmf_set_attr_at_index(fk_attrlist, j,
3979		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
3980		j++;
3981
3982		kmf_set_attr_at_index(fk_attrlist, j,
3983		    KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
3984		j++;
3985
3986		kmf_set_attr_at_index(fk_attrlist, j,
3987		    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
3988		j++;
3989
3990		kmf_set_attr_at_index(fk_attrlist, j,
3991		    KMF_CERT_DATA_ATTR, &certlist[i].certificate,
3992		    sizeof (KMF_DATA));
3993		j++;
3994
3995		kmf_set_attr_at_index(fk_attrlist, j,
3996		    KMF_KEY_HANDLE_ATTR, &newkey, sizeof (KMF_KEY_HANDLE));
3997		j++;
3998
3999		rv = KMFPK11_FindPrikeyByCert(handle, j, fk_attrlist);
4000		if (rv == KMF_OK) {
4001			numkeys++;
4002			keylist = realloc(keylist,
4003			    numkeys * sizeof (KMF_KEY_HANDLE));
4004			if (keylist == NULL) {
4005				rv = KMF_ERR_MEMORY;
4006				goto out;
4007			}
4008			keylist[numkeys - 1] = newkey;
4009		} else if (rv == KMF_ERR_KEY_NOT_FOUND) {
4010			/* it is OK if a key is not found */
4011			rv = KMF_OK;
4012		}
4013	}
4014
4015	if (rv != KMF_OK)
4016		goto out;
4017
4018	rv = kmf_build_pk12(handle, numcerts, certlist, numkeys, keylist,
4019	    p12cred, filename);
4020
4021out:
4022	if (certlist != NULL) {
4023		for (i = 0; i < numcerts; i++)
4024			kmf_free_kmf_cert(handle, &certlist[i]);
4025		free(certlist);
4026	}
4027	if (keylist != NULL) {
4028		for (i = 0; i < numkeys; i++)
4029			kmf_free_kmf_key(handle, &keylist[i]);
4030		free(keylist);
4031	}
4032
4033	return (rv);
4034}
4035