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