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