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