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 == NULL)
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 = NULL;
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 = { NULL, 0};
1268	KMF_DATA  cert2 = { NULL, 0};
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 = {NULL, 0};
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 = { NULL, 0 };
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 = { NULL, 0 };
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 = {NULL, 0};
3202	KMF_DATA	subject = {NULL, 0};
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	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
3252	if (cert != NULL) {
3253		id.Data = NULL;
3254		id.Length = 0;
3255		rv = kmf_get_cert_id_data(cert, &id);
3256		if (rv != KMF_OK) {
3257			goto cleanup;
3258		}
3259
3260		rv = DerDecodeSignedCertificate((const KMF_DATA *)cert, &x509);
3261		if (rv != KMF_OK) {
3262			goto cleanup;
3263		}
3264
3265		rv = DerEncodeName(&x509->certificate.subject, &subject);
3266		if (rv != KMF_OK) {
3267			goto cleanup;
3268		}
3269		SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length);
3270		i++;
3271
3272		rv = kmf_get_cert_start_date_str(handle, cert, &notbefore);
3273		if (rv != KMF_OK) {
3274			goto cleanup;
3275		}
3276		start = convertDate(notbefore);
3277		free(notbefore);
3278
3279		rv = kmf_get_cert_end_date_str(handle, cert, &notafter);
3280		if (rv != KMF_OK) {
3281			goto cleanup;
3282		}
3283		end = convertDate(notafter);
3284		free(notafter);
3285		if (id.Data != NULL && id.Data != NULL && id.Length > 0) {
3286			SETATTR(templ, i, CKA_ID, id.Data, id.Length);
3287			i++;
3288		}
3289		if (start != NULL) {
3290			/*
3291			 * This makes some potentially dangerous assumptions:
3292			 *  1. that the startdate in the parameter block is
3293			 * properly formatted as YYYYMMDD
3294			 *  2. That the CK_DATE structure is always the same.
3295			 */
3296			(void) memcpy(&startdate, start, sizeof (CK_DATE));
3297			SETATTR(templ, i, CKA_START_DATE, &startdate,
3298			    sizeof (startdate));
3299			i++;
3300		}
3301		if (end != NULL) {
3302			(void) memcpy(&enddate, end, sizeof (CK_DATE));
3303			SETATTR(templ, i, CKA_END_DATE, &enddate,
3304			    sizeof (enddate));
3305			i++;
3306		}
3307
3308		if ((rv = kmf_get_cert_ku(cert, &kuext)) != KMF_OK &&
3309		    rv != KMF_ERR_EXTENSION_NOT_FOUND)
3310			goto cleanup;
3311
3312		kufound = (rv == KMF_OK);
3313		rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND */
3314	}
3315
3316	/*
3317	 * Only set the KeyUsage stuff if the KU extension was present.
3318	 */
3319	if (kufound) {
3320		CK_BBOOL	condition;
3321
3322		condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
3323		    B_TRUE : B_FALSE;
3324		SETATTR(templ, i, CKA_UNWRAP, &condition, sizeof (CK_BBOOL));
3325		i++;
3326		condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
3327		    B_TRUE : B_FALSE;
3328		SETATTR(templ, i, CKA_DECRYPT, &condition, sizeof (CK_BBOOL));
3329		i++;
3330		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3331		    B_TRUE : B_FALSE;
3332		SETATTR(templ, i, CKA_SIGN, &condition,	sizeof (CK_BBOOL));
3333		i++;
3334		condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
3335		    B_TRUE : B_FALSE;
3336		SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
3337		    sizeof (CK_BBOOL));
3338		i++;
3339
3340	}
3341
3342	if (keylabel != NULL) {
3343		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3344		i++;
3345	}
3346	if (id.Data == NULL && rawkey->id.Data != NULL) {
3347		SETATTR(templ, i, CKA_ID, rawkey->id.Data,
3348		    rawkey->id.Length);
3349		i++;
3350	}
3351	if (keytype == CKK_RSA) {
3352		SETATTR(templ, i, CKA_MODULUS,
3353		    rawkey->rawdata.rsa.mod.val,
3354		    rawkey->rawdata.rsa.mod.len);
3355		i++;
3356		SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
3357		    rawkey->rawdata.rsa.pubexp.val,
3358		    rawkey->rawdata.rsa.pubexp.len);
3359		i++;
3360		if (rawkey->rawdata.rsa.priexp.val != NULL) {
3361			SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
3362			    rawkey->rawdata.rsa.priexp.val,
3363			    rawkey->rawdata.rsa.priexp.len);
3364			i++;
3365		}
3366		if (rawkey->rawdata.rsa.prime1.val != NULL) {
3367			SETATTR(templ, i, CKA_PRIME_1,
3368			    rawkey->rawdata.rsa.prime1.val,
3369			    rawkey->rawdata.rsa.prime1.len);
3370			i++;
3371		}
3372		if (rawkey->rawdata.rsa.prime2.val != NULL) {
3373			SETATTR(templ, i, CKA_PRIME_2,
3374			    rawkey->rawdata.rsa.prime2.val,
3375			    rawkey->rawdata.rsa.prime2.len);
3376			i++;
3377		}
3378		if (rawkey->rawdata.rsa.exp1.val != NULL) {
3379			SETATTR(templ, i, CKA_EXPONENT_1,
3380			    rawkey->rawdata.rsa.exp1.val,
3381			    rawkey->rawdata.rsa.exp1.len);
3382			i++;
3383		}
3384		if (rawkey->rawdata.rsa.exp2.val != NULL) {
3385			SETATTR(templ, i, CKA_EXPONENT_2,
3386			    rawkey->rawdata.rsa.exp2.val,
3387			    rawkey->rawdata.rsa.exp2.len);
3388			i++;
3389		}
3390		if (rawkey->rawdata.rsa.coef.val != NULL) {
3391			SETATTR(templ, i, CKA_COEFFICIENT,
3392			    rawkey->rawdata.rsa.coef.val,
3393			    rawkey->rawdata.rsa.coef.len);
3394			i++;
3395		}
3396	} else if (keytype == CKK_DSA) {
3397		SETATTR(templ, i, CKA_PRIME,
3398		    rawkey->rawdata.dsa.prime.val,
3399		    rawkey->rawdata.dsa.prime.len);
3400		i++;
3401		SETATTR(templ, i, CKA_SUBPRIME,
3402		    rawkey->rawdata.dsa.subprime.val,
3403		    rawkey->rawdata.dsa.subprime.len);
3404		i++;
3405		SETATTR(templ, i, CKA_BASE,
3406		    rawkey->rawdata.dsa.base.val,
3407		    rawkey->rawdata.dsa.base.len);
3408		i++;
3409		SETATTR(templ, i, CKA_VALUE,
3410		    rawkey->rawdata.dsa.value.val,
3411		    rawkey->rawdata.dsa.value.len);
3412		i++;
3413	} else if (keytype == CKK_EC) {
3414		SETATTR(templ, i, CKA_SIGN, &cktrue, sizeof (cktrue));
3415		i++;
3416		SETATTR(templ, i, CKA_DERIVE, &cktrue, sizeof (cktrue));
3417		i++;
3418		SETATTR(templ, i, CKA_VALUE,
3419		    rawkey->rawdata.ec.value.val,
3420		    rawkey->rawdata.ec.value.len);
3421		i++;
3422		SETATTR(templ, i, CKA_EC_PARAMS,
3423		    rawkey->rawdata.ec.params.Data,
3424		    rawkey->rawdata.ec.params.Length);
3425		i++;
3426	}
3427
3428	ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
3429	if (ckrv != CKR_OK) {
3430		SET_ERROR(kmfh, ckrv);
3431
3432		/* Report authentication failures to the caller */
3433		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3434		    ckrv == CKR_PIN_INCORRECT ||
3435		    ckrv == CKR_PIN_INVALID ||
3436		    ckrv == CKR_PIN_EXPIRED ||
3437		    ckrv == CKR_PIN_LOCKED ||
3438		    ckrv == CKR_SESSION_READ_ONLY)
3439			rv = KMF_ERR_AUTH_FAILED;
3440		else
3441			rv = KMF_ERR_INTERNAL;
3442	}
3443cleanup:
3444	if (start != NULL)
3445		free(start);
3446	if (end != NULL)
3447		free(end);
3448	kmf_free_data(&id);
3449	kmf_free_data(&subject);
3450	kmf_free_signed_cert(x509);
3451	free(x509);
3452
3453	return (rv);
3454}
3455
3456KMF_RETURN
3457KMFPK11_CreateSymKey(KMF_HANDLE_T handle,
3458    int numattr, KMF_ATTRIBUTE *attrlist)
3459{
3460	KMF_RETURN		rv = KMF_OK;
3461	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3462	CK_RV			ckrv;
3463	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3464	CK_OBJECT_HANDLE	keyhandle;
3465	CK_MECHANISM		keyGenMech;
3466	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3467	CK_ULONG		secKeyType;
3468	CK_ULONG		secKeyLen;	/* for RC4 and AES */
3469	CK_BBOOL		true = TRUE;
3470	CK_BBOOL		false = FALSE;
3471	CK_ATTRIBUTE		templ[15];
3472	CK_BYTE			*keydata = NULL;
3473	int			i = 0;
3474	KMF_KEY_HANDLE		*symkey;
3475	KMF_KEY_ALG		keytype;
3476	uint32_t		keylen = 0;
3477	uint32_t		attrkeylen = 0;
3478	uint32_t		keylen_size = sizeof (uint32_t);
3479	char			*keylabel = NULL;
3480	KMF_CREDENTIAL		*cred = NULL;
3481	uint32_t		is_sensitive = B_FALSE;
3482	uint32_t		is_not_extractable = B_FALSE;
3483
3484	if (kmfh == NULL)
3485		return (KMF_ERR_UNINITIALIZED);
3486
3487	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3488		return (KMF_ERR_NO_TOKEN_SELECTED);
3489
3490	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3491	if (symkey == NULL)
3492		return (KMF_ERR_BAD_PARAMETER);
3493
3494	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
3495	    (void *)&keytype, NULL);
3496	if (rv != KMF_OK)
3497		return (KMF_ERR_BAD_PARAMETER);
3498
3499	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3500	if (keylabel == NULL)
3501		return (KMF_ERR_BAD_PARAMETER);
3502
3503	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3504	    (void *)&is_sensitive, NULL);
3505	if (rv != KMF_OK)
3506		return (KMF_ERR_BAD_PARAMETER);
3507
3508	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3509	    (void *)&is_not_extractable, NULL);
3510	if (rv != KMF_OK)
3511		return (KMF_ERR_BAD_PARAMETER);
3512
3513	/*
3514	 * For AES, RC4, DES and 3DES, call C_GenerateKey() to create a key.
3515	 *
3516	 * For a generic secret key, because it may not be supported in
3517	 * C_GenerateKey() for some PKCS11 providers, we will handle it
3518	 * differently.
3519	 */
3520	if (keytype == KMF_GENERIC_SECRET) {
3521		rv = create_generic_secret_key(handle, numattr,
3522		    attrlist, &keyhandle);
3523		if (rv != KMF_OK)
3524			goto out;
3525		else
3526			goto setup;
3527	}
3528
3529	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3530	    NULL, &attrkeylen);
3531	if (rv == KMF_OK && attrkeylen > 0) {
3532		keydata = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3533		    numattr);
3534	} else {
3535		keydata = NULL;
3536		attrkeylen = 0;
3537		rv = KMF_OK;
3538	}
3539	if (keydata != NULL) {
3540		if (keytype == KMF_DES && attrkeylen != 8) {
3541			rv = KMF_ERR_BAD_KEY_SIZE;
3542			goto out;
3543		}
3544		if (keytype == KMF_DES3 && attrkeylen != 24) {
3545			rv = KMF_ERR_BAD_KEY_SIZE;
3546			goto out;
3547		}
3548		/*
3549		 * This may override what the user gave on the
3550		 * command line.
3551		 */
3552		keylen = attrkeylen * 8; /* bytes to bits */
3553	} else {
3554		/*
3555		 * If keydata was not given, key length must be
3556		 * provided.
3557		 */
3558		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3559		    &keylen, &keylen_size);
3560		if (rv == KMF_ERR_ATTR_NOT_FOUND &&
3561		    (keytype == KMF_DES || keytype == KMF_DES3))
3562			/* keylength is not required for DES and 3DES */
3563			rv = KMF_OK;
3564		if (rv != KMF_OK)
3565			return (KMF_ERR_BAD_PARAMETER);
3566	}
3567
3568	if ((keylen % 8) != 0) {
3569		return (KMF_ERR_BAD_KEY_SIZE);
3570	}
3571	secKeyLen = keylen / 8;  /* in bytes for RC4/AES */
3572
3573	/*
3574	 * Only set CKA_VALUE_LEN if the key data was not given and
3575	 * we are creating an RC4 or AES key.
3576	 */
3577	if (keydata == NULL &&
3578	    (keytype == KMF_AES || keytype == KMF_RC4)) {
3579		SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
3580		    sizeof (secKeyLen));
3581		i++;
3582	}
3583
3584	/* Other keytypes */
3585	keyGenMech.pParameter = NULL_PTR;
3586	keyGenMech.ulParameterLen = 0;
3587	switch (keytype) {
3588		case KMF_AES:
3589			keyGenMech.mechanism = CKM_AES_KEY_GEN;
3590			secKeyType = CKK_AES;
3591			break;
3592		case KMF_RC4:
3593			keyGenMech.mechanism = CKM_RC4_KEY_GEN;
3594			secKeyType = CKK_RC4;
3595			break;
3596		case KMF_DES:
3597			keyGenMech.mechanism = CKM_DES_KEY_GEN;
3598			secKeyType = CKK_DES;
3599			break;
3600		case KMF_DES3:
3601			keyGenMech.mechanism = CKM_DES3_KEY_GEN;
3602			secKeyType = CKK_DES3;
3603			break;
3604		default:
3605			return (KMF_ERR_BAD_KEY_TYPE);
3606	}
3607	if (keydata != NULL) {
3608		SETATTR(templ, i, CKA_VALUE, keydata, secKeyLen);
3609		i++;
3610	}
3611	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3612	i++;
3613	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3614	i++;
3615
3616	if (keylabel != NULL) {
3617		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3618		i++;
3619	}
3620
3621	if (is_sensitive == B_TRUE) {
3622		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3623	} else {
3624		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3625	}
3626	i++;
3627
3628	if (is_not_extractable == B_TRUE) {
3629		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3630	} else {
3631		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3632	}
3633	i++;
3634
3635	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3636	i++;
3637	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3638	i++;
3639	SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
3640	i++;
3641	SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
3642	i++;
3643	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3644	i++;
3645	SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
3646	i++;
3647
3648	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3649	if (cred == NULL)
3650		return (KMF_ERR_BAD_PARAMETER);
3651
3652	rv = pk11_authenticate(handle, cred);
3653	if (rv != KMF_OK) {
3654		return (rv);
3655	}
3656
3657	/* If the key data was given, use C_CreateObject */
3658	if (keydata != NULL) {
3659		ckrv = C_CreateObject(hSession, templ, i, &keyhandle);
3660	} else {
3661		ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i,
3662		    &keyhandle);
3663	}
3664	if (ckrv != CKR_OK) {
3665		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3666		    ckrv == CKR_PIN_INCORRECT ||
3667		    ckrv == CKR_PIN_INVALID ||
3668		    ckrv == CKR_PIN_EXPIRED ||
3669		    ckrv == CKR_PIN_LOCKED ||
3670		    ckrv == CKR_SESSION_READ_ONLY)
3671			rv = KMF_ERR_AUTH_FAILED;
3672		else
3673			rv = KMF_ERR_KEYGEN_FAILED;
3674		SET_ERROR(kmfh, ckrv);
3675		goto out;
3676	}
3677
3678setup:
3679	symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
3680	symkey->keyalg = keytype;
3681	symkey->keyclass = KMF_SYMMETRIC;
3682	symkey->israw = FALSE;
3683	symkey->keyp = (void *)keyhandle;
3684
3685out:
3686	return (rv);
3687}
3688
3689KMF_RETURN
3690KMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
3691    KMF_RAW_SYM_KEY *rkey)
3692{
3693	KMF_RETURN		rv = KMF_OK;
3694	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3695
3696	if (kmfh == NULL)
3697		return (KMF_ERR_UNINITIALIZED);
3698
3699	if (kmfh->pk11handle == CK_INVALID_HANDLE)
3700		return (KMF_ERR_NO_TOKEN_SELECTED);
3701
3702	if (symkey == NULL || rkey == NULL)
3703		return (KMF_ERR_BAD_PARAMETER);
3704	else if (symkey->keyclass != KMF_SYMMETRIC)
3705		return (KMF_ERR_BAD_KEY_CLASS);
3706
3707	/*
3708	 * If the key is already in "raw" format, copy the data
3709	 * to the new record if possible.
3710	 */
3711	if (symkey->israw) {
3712		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
3713
3714		if (rawkey == NULL)
3715			return (KMF_ERR_BAD_KEYHANDLE);
3716		if (rawkey->sensitive)
3717			return (KMF_ERR_SENSITIVE_KEY);
3718		if (rawkey->not_extractable)
3719			return (KMF_ERR_UNEXTRACTABLE_KEY);
3720
3721		if (rawkey->rawdata.sym.keydata.val == NULL ||
3722		    rawkey->rawdata.sym.keydata.len == 0)
3723			return (KMF_ERR_GETKEYVALUE_FAILED);
3724
3725		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
3726		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
3727			return (KMF_ERR_MEMORY);
3728		(void) memcpy(rkey->keydata.val,
3729		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
3730	} else {
3731		rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
3732	}
3733
3734	return (rv);
3735}
3736
3737KMF_RETURN
3738KMFPK11_SetTokenPin(KMF_HANDLE_T handle,
3739	int numattr, KMF_ATTRIBUTE *attrlist)
3740{
3741	KMF_RETURN	ret = KMF_OK;
3742	CK_RV		rv = CKR_OK;
3743	KMF_HANDLE	*kmfh = (KMF_HANDLE *)handle;
3744	CK_SESSION_HANDLE	session = NULL;
3745	KMF_CREDENTIAL	*oldcred;
3746	KMF_CREDENTIAL	*newcred;
3747	CK_SLOT_ID	slotid;
3748	CK_USER_TYPE	user = CKU_USER;
3749
3750	if (handle == NULL || attrlist == NULL || numattr == 0)
3751		return (KMF_ERR_BAD_PARAMETER);
3752
3753	oldcred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3754	if (oldcred == NULL)
3755		return (KMF_ERR_BAD_PARAMETER);
3756
3757	newcred = kmf_get_attr_ptr(KMF_NEWPIN_ATTR, attrlist, numattr);
3758	if (newcred == NULL)
3759		return (KMF_ERR_BAD_PARAMETER);
3760
3761	rv = kmf_get_attr(KMF_SLOT_ID_ATTR, attrlist, numattr,
3762	    (void *)&slotid, NULL);
3763	if (rv != KMF_OK) {
3764		char *tokenlabel = NULL;
3765		/*
3766		 * If a slot wasn't given, the user must pass
3767		 * a token label so we can find the slot here.
3768		 */
3769		tokenlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
3770		    numattr);
3771		if (tokenlabel == NULL)
3772			return (KMF_ERR_BAD_PARAMETER);
3773
3774		rv = kmf_pk11_token_lookup(handle, tokenlabel, &slotid);
3775		if (rv != KMF_OK)
3776			return (rv);
3777	}
3778	rv = kmf_get_attr(KMF_PK11_USER_TYPE_ATTR, attrlist, numattr,
3779	    (void *)&user, NULL);
3780	if (rv != CKR_OK)
3781		user = CKU_USER;
3782
3783	rv = C_OpenSession(slotid, CKF_SERIAL_SESSION | CKF_RW_SESSION,
3784	    NULL, NULL, &session);
3785	if (rv != CKR_OK) {
3786		SET_ERROR(kmfh, rv);
3787		ret = KMF_ERR_UNINITIALIZED;
3788		goto end;
3789	}
3790
3791	rv = C_Login(session, user, (CK_BYTE *)oldcred->cred,
3792	    oldcred->credlen);
3793	if (rv != CKR_OK) {
3794		SET_ERROR(kmfh, rv);
3795		if (rv == CKR_PIN_INCORRECT ||
3796		    rv == CKR_PIN_INVALID ||
3797		    rv == CKR_PIN_EXPIRED ||
3798		    rv == CKR_PIN_LOCKED)
3799			ret = KMF_ERR_AUTH_FAILED;
3800		else
3801			ret = KMF_ERR_INTERNAL;
3802
3803		goto end;
3804	}
3805
3806	rv = C_SetPIN(session,
3807	    (CK_BYTE *)oldcred->cred, oldcred->credlen,
3808	    (CK_BYTE *)newcred->cred, newcred->credlen);
3809
3810	if (rv != CKR_OK) {
3811		SET_ERROR(kmfh, rv);
3812		if (rv == CKR_PIN_INCORRECT ||
3813		    rv == CKR_PIN_INVALID ||
3814		    rv == CKR_PIN_EXPIRED ||
3815		    rv == CKR_PIN_LOCKED)
3816			ret = KMF_ERR_AUTH_FAILED;
3817		else
3818			ret = KMF_ERR_INTERNAL;
3819	}
3820end:
3821	if (session != NULL)
3822		(void) C_CloseSession(session);
3823	return (ret);
3824}
3825
3826static KMF_RETURN
3827create_generic_secret_key(KMF_HANDLE_T handle,
3828	int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key)
3829{
3830	KMF_RETURN		rv = KMF_OK;
3831	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
3832	CK_RV			ckrv;
3833	CK_SESSION_HANDLE	hSession = kmfh->pk11handle;
3834	CK_OBJECT_CLASS		class = CKO_SECRET_KEY;
3835	CK_ULONG		secKeyType = CKK_GENERIC_SECRET;
3836	CK_ULONG		secKeyLen;
3837	CK_BBOOL		true = TRUE;
3838	CK_BBOOL		false = FALSE;
3839	CK_ATTRIBUTE		templ[15];
3840	int			i;
3841	int			random_fd = -1;
3842	int			nread;
3843	int			freebuf = 0;
3844	char			*buf = NULL;
3845	uint32_t		keylen = 0, attrkeylen = 0;
3846	char			*keylabel = NULL;
3847	KMF_CREDENTIAL		*cred;
3848	uint32_t is_sensitive, is_not_extractable;
3849
3850	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
3851	if (keylabel == NULL)
3852		return (KMF_ERR_BAD_PARAMETER);
3853
3854	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
3855	if (cred == NULL)
3856		return (KMF_ERR_BAD_PARAMETER);
3857
3858	rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
3859	    (void *)&is_sensitive, NULL);
3860	if (rv != KMF_OK)
3861		return (KMF_ERR_BAD_PARAMETER);
3862
3863	rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
3864	    (void *)&is_not_extractable, NULL);
3865	if (rv != KMF_OK)
3866		return (KMF_ERR_BAD_PARAMETER);
3867
3868	rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
3869	    NULL, &attrkeylen);
3870	if (rv == KMF_OK && attrkeylen > 0) {
3871		buf = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
3872		    numattr);
3873		secKeyLen = attrkeylen;
3874	} else {
3875		buf = NULL;
3876		rv = KMF_OK;
3877	}
3878	if (buf == NULL) {
3879		/*
3880		 * If the key data was not given, key length must
3881		 * be provided.
3882		 */
3883		rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
3884		    &keylen, NULL);
3885		if (rv != KMF_OK)
3886			return (KMF_ERR_BAD_PARAMETER);
3887
3888		/*
3889		 * Check the key size.
3890		 */
3891		if ((keylen % 8) != 0) {
3892			return (KMF_ERR_BAD_KEY_SIZE);
3893		} else {
3894			secKeyLen = keylen/8;  /* in bytes */
3895		}
3896
3897		/*
3898		 * Generate a random number with the key size first.
3899		 */
3900		buf = malloc(secKeyLen);
3901		if (buf == NULL)
3902			return (KMF_ERR_MEMORY);
3903
3904		freebuf = 1;
3905		while ((random_fd = open(DEV_RANDOM, O_RDONLY)) < 0) {
3906			if (errno != EINTR)
3907				break;
3908		}
3909
3910		if (random_fd < 0) {
3911			rv = KMF_ERR_KEYGEN_FAILED;
3912			goto out;
3913		}
3914
3915		nread = read(random_fd, buf, secKeyLen);
3916		if (nread <= 0 || nread != secKeyLen) {
3917			rv = KMF_ERR_KEYGEN_FAILED;
3918			goto out;
3919		}
3920	}
3921
3922	/*
3923	 * Authenticate into the token and call C_CreateObject to generate
3924	 * a generic secret token key.
3925	 */
3926	rv = pk11_authenticate(handle, cred);
3927	if (rv != KMF_OK) {
3928		goto out;
3929	}
3930
3931	i = 0;
3932	SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
3933	i++;
3934	SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
3935	i++;
3936	SETATTR(templ, i, CKA_VALUE, buf, secKeyLen);
3937	i++;
3938
3939	if (keylabel != NULL) {
3940		SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
3941		i++;
3942	}
3943
3944	if (is_sensitive == B_TRUE) {
3945		SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
3946	} else {
3947		SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
3948	}
3949	i++;
3950
3951	if (is_not_extractable == B_TRUE) {
3952		SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
3953	} else {
3954		SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
3955	}
3956	i++;
3957
3958	SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
3959	i++;
3960	SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
3961	i++;
3962	SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
3963	i++;
3964
3965	ckrv = C_CreateObject(hSession, templ, i, key);
3966	if (ckrv != CKR_OK) {
3967		if (ckrv == CKR_USER_NOT_LOGGED_IN ||
3968		    ckrv == CKR_PIN_INCORRECT ||
3969		    ckrv == CKR_PIN_INVALID ||
3970		    ckrv == CKR_PIN_EXPIRED ||
3971		    ckrv == CKR_PIN_LOCKED ||
3972		    ckrv == CKR_SESSION_READ_ONLY)
3973			rv = KMF_ERR_AUTH_FAILED;
3974		else
3975			rv = KMF_ERR_KEYGEN_FAILED;
3976		SET_ERROR(kmfh, ckrv);
3977	}
3978
3979out:
3980	if (buf != NULL && freebuf)
3981		free(buf);
3982
3983	if (random_fd != -1)
3984		(void) close(random_fd);
3985
3986	return (rv);
3987}
3988
3989KMF_RETURN
3990KMFPK11_StoreKey(KMF_HANDLE_T handle,
3991	int numattr,
3992	KMF_ATTRIBUTE *attlist)
3993{
3994	KMF_RETURN rv = KMF_OK;
3995	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3996	KMF_CREDENTIAL cred = {NULL, 0};
3997	KMF_KEY_HANDLE *key;
3998	KMF_RAW_KEY_DATA *rawkey = NULL;
3999	CK_BBOOL btrue = TRUE;
4000	CK_ATTRIBUTE tokenattr[1];
4001	CK_OBJECT_HANDLE newobj;
4002	CK_RV ckrv;
4003
4004	if (kmfh == NULL)
4005		return (KMF_ERR_UNINITIALIZED);
4006
4007	if (kmfh->pk11handle == CK_INVALID_HANDLE)
4008		return (KMF_ERR_NO_TOKEN_SELECTED);
4009
4010	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attlist, numattr,
4011	    (void *)&cred, NULL);
4012	if (rv != KMF_OK)
4013		return (KMF_ERR_BAD_PARAMETER);
4014
4015	rv = pk11_authenticate(handle, &cred);
4016	if (rv != KMF_OK)
4017		return (rv);
4018
4019	key = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
4020	if (key == NULL) {
4021		key = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist,
4022		    numattr);
4023		if (key == NULL)
4024			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attlist,
4025			    numattr);
4026	}
4027	if (key == NULL && rawkey == NULL)
4028		return (KMF_ERR_ATTR_NOT_FOUND);
4029
4030	if (rawkey != NULL) {
4031		rv = store_raw_key(handle, attlist, numattr, rawkey);
4032	} else if (key && key->kstype == KMF_KEYSTORE_PK11TOKEN) {
4033
4034		SETATTR(tokenattr, 0, CKA_TOKEN, &btrue, sizeof (btrue));
4035		/* Copy the key object to the token */
4036		ckrv = C_CopyObject(kmfh->pk11handle,
4037		    (CK_OBJECT_HANDLE)key->keyp, tokenattr, 1, &newobj);
4038		if (ckrv != CKR_OK)  {
4039			SET_ERROR(kmfh, ckrv);
4040			return (KMF_ERR_INTERNAL);
4041		}
4042
4043		/* Replace the object handle with the new token-based one */
4044		ckrv = C_DestroyObject(kmfh->pk11handle,
4045		    (CK_OBJECT_HANDLE)key->keyp);
4046		if (ckrv != CKR_OK)  {
4047			SET_ERROR(kmfh, ckrv);
4048			return (KMF_ERR_INTERNAL);
4049		}
4050		key->keyp = (void *)newobj;
4051	} else {
4052		rv = KMF_ERR_BAD_PARAMETER;
4053	}
4054
4055	return (rv);
4056}
4057
4058
4059KMF_RETURN
4060KMFPK11_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4061{
4062	KMF_RETURN rv = KMF_OK;
4063	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4064	KMF_CREDENTIAL *cred = NULL;
4065	KMF_CREDENTIAL *p12cred = NULL;
4066	char *filename = NULL;
4067	KMF_X509_DER_CERT *certlist = NULL;
4068	KMF_KEY_HANDLE *keylist = NULL;
4069	uint32_t numcerts;
4070	uint32_t numkeys;
4071	char *certlabel = NULL;
4072	char *issuer = NULL;
4073	char *subject = NULL;
4074	KMF_BIGINT *serial = NULL;
4075	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
4076	KMF_ATTRIBUTE fc_attrlist[16];
4077	int i;
4078
4079	if (kmfh == NULL)
4080		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
4081
4082	if (kmfh->pk11handle == CK_INVALID_HANDLE)
4083		return (KMF_ERR_NO_TOKEN_SELECTED);
4084
4085	/* First get the required attributes */
4086	cred =  kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
4087	if (cred == NULL)
4088		return (KMF_ERR_BAD_PARAMETER);
4089
4090	p12cred =  kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
4091	if (p12cred == NULL)
4092		return (KMF_ERR_BAD_PARAMETER);
4093
4094	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
4095	    numattr);
4096	if (filename == NULL)
4097		return (KMF_ERR_BAD_PARAMETER);
4098
4099	/* Find all the certificates that match the searching criteria */
4100	i = 0;
4101	kmf_set_attr_at_index(fc_attrlist, i,
4102	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
4103	i++;
4104
4105	kmf_set_attr_at_index(fc_attrlist, i,
4106	    KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
4107	i++;
4108
4109	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
4110	if (certlabel != NULL) {
4111		kmf_set_attr_at_index(fc_attrlist, i,
4112		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
4113		i++;
4114	}
4115
4116	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
4117	if (issuer != NULL) {
4118		kmf_set_attr_at_index(fc_attrlist, i,
4119		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
4120		i++;
4121	}
4122
4123	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
4124	if (subject != NULL) {
4125		kmf_set_attr_at_index(fc_attrlist, i,
4126		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
4127		i++;
4128	}
4129
4130	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
4131	if (serial != NULL) {
4132		kmf_set_attr_at_index(fc_attrlist, i,
4133		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
4134		i++;
4135	}
4136
4137	rv = KMFPK11_FindCert(handle, i, fc_attrlist);
4138
4139	if (rv == KMF_OK && numcerts > 0) {
4140		certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
4141		    sizeof (KMF_X509_DER_CERT));
4142		if (certlist == NULL)
4143			return (KMF_ERR_MEMORY);
4144
4145		(void) memset(certlist, 0, numcerts *
4146		    sizeof (KMF_X509_DER_CERT));
4147
4148		kmf_set_attr_at_index(fc_attrlist, i, KMF_X509_DER_CERT_ATTR,
4149		    certlist, sizeof (KMF_X509_DER_CERT));
4150		i++;
4151
4152		rv = kmf_find_cert(handle, i, fc_attrlist);
4153		if (rv != KMF_OK) {
4154			free(certlist);
4155			return (rv);
4156		}
4157	} else {
4158		return (rv);
4159	}
4160
4161	/* For each certificate, find the matching private key */
4162	numkeys = 0;
4163	for (i = 0; i < numcerts; i++) {
4164		KMF_ATTRIBUTE fk_attrlist[16];
4165		int j = 0;
4166		KMF_KEY_HANDLE newkey;
4167		KMF_ENCODE_FORMAT format = KMF_FORMAT_RAWKEY;
4168
4169		kmf_set_attr_at_index(fk_attrlist, j,
4170		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
4171		j++;
4172
4173		kmf_set_attr_at_index(fk_attrlist, j,
4174		    KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
4175		j++;
4176
4177		kmf_set_attr_at_index(fk_attrlist, j,
4178		    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
4179		j++;
4180
4181		kmf_set_attr_at_index(fk_attrlist, j,
4182		    KMF_CERT_DATA_ATTR, &certlist[i].certificate,
4183		    sizeof (KMF_DATA));
4184		j++;
4185
4186		kmf_set_attr_at_index(fk_attrlist, j,
4187		    KMF_KEY_HANDLE_ATTR, &newkey, sizeof (KMF_KEY_HANDLE));
4188		j++;
4189
4190		rv = KMFPK11_FindPrikeyByCert(handle, j, fk_attrlist);
4191		if (rv == KMF_OK) {
4192			numkeys++;
4193			keylist = realloc(keylist,
4194			    numkeys * sizeof (KMF_KEY_HANDLE));
4195			if (keylist == NULL) {
4196				rv = KMF_ERR_MEMORY;
4197				goto out;
4198			}
4199			keylist[numkeys - 1] = newkey;
4200		} else if (rv == KMF_ERR_KEY_NOT_FOUND) {
4201			/* it is OK if a key is not found */
4202			rv = KMF_OK;
4203		}
4204	}
4205
4206	if (rv != KMF_OK)
4207		goto out;
4208
4209	rv = kmf_build_pk12(handle, numcerts, certlist, numkeys, keylist,
4210	    p12cred, filename);
4211
4212out:
4213	if (certlist != NULL) {
4214		for (i = 0; i < numcerts; i++)
4215			kmf_free_kmf_cert(handle, &certlist[i]);
4216		free(certlist);
4217	}
4218	if (keylist != NULL) {
4219		for (i = 0; i < numkeys; i++)
4220			kmf_free_kmf_key(handle, &keylist[i]);
4221		free(keylist);
4222	}
4223
4224	return (rv);
4225}
4226