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