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