nss_spi.c revision 5051:cbbb7c8b40a9
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 * NSS keystore wrapper
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 <sys/types.h>
31#include <sys/stat.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <synch.h>
35
36#include <kmfapiP.h>
37#include <ber_der.h>
38/* NSS related headers */
39
40#include <mps/nss.h>
41#include <mps/cert.h>
42#include <mps/certdb.h>
43#include <mps/secoid.h>
44#include <mps/secder.h>
45#include <mps/secerr.h>
46#include <mps/cryptohi.h>
47#include <mps/keyhi.h>
48#include <mps/keythi.h>
49#include <mps/pk11func.h>
50#include <mps/pk11pqg.h>
51#include <mps/pkcs12.h>
52#include <mps/p12plcy.h>
53#include <mps/prerror.h>
54
55#define	NSS_OK		0
56
57mutex_t init_lock = DEFAULTMUTEX;
58static int nss_initialized = 0;
59
60KMF_RETURN
61NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
62
63KMF_RETURN
64NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
65
66void
67NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
68
69KMF_RETURN
70NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
71
72KMF_RETURN
73NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
74
75KMF_RETURN
76NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
77
78KMF_RETURN
79NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
80
81KMF_RETURN
82NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
83
84KMF_RETURN
85NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
86
87KMF_RETURN
88NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
89	KMF_DATA *, KMF_DATA *);
90
91KMF_RETURN
92NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
93
94KMF_RETURN
95NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
96
97KMF_RETURN
98NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
99
100KMF_RETURN
101NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
102
103KMF_RETURN
104NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
105
106KMF_RETURN
107NSS_GetErrorString(KMF_HANDLE_T, char **);
108
109KMF_RETURN
110NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
111
112KMF_RETURN
113NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
114
115KMF_RETURN
116NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
117	KMF_DATA *, KMF_DATA *);
118
119KMF_RETURN
120NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
121
122KMF_RETURN
123NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
124
125KMF_RETURN
126NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127
128KMF_RETURN
129NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
130
131static
132KMF_PLUGIN_FUNCLIST nss_plugin_table =
133{
134	1,				/* Version */
135	NSS_ConfigureKeystore,
136	NSS_FindCert,
137	NSS_FreeKMFCert,
138	NSS_StoreCert,
139	NSS_ImportCert,
140	NSS_ImportCRL,
141	NSS_DeleteCert,
142	NSS_DeleteCRL,
143	NSS_CreateKeypair,
144	NSS_FindKey,
145	NSS_EncodePubKeyData,
146	NSS_SignData,
147	NSS_DeleteKey,
148	NULL    /* ListCRL */,
149	NSS_FindCRL,
150	NSS_FindCertInCRL,
151	NSS_GetErrorString,
152	NSS_FindPrikeyByCert,
153	NSS_DecryptData,
154	NSS_ExportPK12,
155	NSS_CreateSymKey,
156	NSS_GetSymKeyValue,
157	NSS_SetTokenPin,
158	NULL, /* VerifyData */
159	NSS_StoreKey,
160	NULL /* Finalize */
161};
162
163/* additions for importing and exporting PKCS 12 files */
164typedef struct p12uContextStr {
165	char		*filename;	/* name of file */
166	PRFileDesc	*file;		/* pointer to file */
167	PRBool		error;		/* error occurred? */
168	int		errorValue;	/* which error occurred? */
169} p12uContext;
170
171#define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
172	h->lasterr.errcode = c;
173
174KMF_PLUGIN_FUNCLIST *
175KMF_Plugin_Initialize()
176{
177	SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
178	SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
179	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
180	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
181	SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
182	SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
183	SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
184
185	return (&nss_plugin_table);
186}
187
188static char *
189/*ARGSUSED*/
190nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
191{
192	if (retry)
193		return (NULL);
194	if (arg != NULL)
195		return ((char *)strdup(arg));
196	else
197		return (NULL);
198}
199
200static KMF_RETURN
201nss_authenticate(KMF_HANDLE_T handle,
202	PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
203{
204
205	SECStatus nssrv = SECSuccess;
206	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
207
208	/* If a password was given, try to login to the slot */
209	if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
210	    nss_slot == NULL) {
211		return (KMF_ERR_BAD_PARAMETER);
212	}
213
214	if (PK11_IsLoggedIn(nss_slot, NULL)) {
215		return (KMF_OK);
216	}
217
218	PK11_SetPasswordFunc(nss_getpassword);
219	nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
220
221	if (nssrv != SECSuccess) {
222		SET_ERROR(kmfh, nssrv);
223		PK11_FreeSlot(nss_slot);
224		return (KMF_ERR_AUTH_FAILED);
225	}
226
227	return (KMF_OK);
228}
229
230static SECStatus
231Init_NSS_DBs(const char *configdir,
232	const char *certPrefix,
233	const char *keyPrefix,
234	const char *secmodName)
235{
236	SECStatus rv = NSS_OK;
237
238	(void) mutex_lock(&init_lock);
239
240	/* If another thread already did it, return OK. */
241	if (nss_initialized) {
242		(void) mutex_unlock(&init_lock);
243		return (SECSuccess);
244	}
245
246	rv = NSS_Initialize((configdir && strlen(configdir)) ?
247	    configdir : "./", certPrefix, keyPrefix,
248	    secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
249	if (rv != SECSuccess) {
250		goto end;
251	}
252
253	nss_initialized++;
254end:
255	(void) mutex_unlock(&init_lock);
256	return (rv);
257}
258
259/*
260 * When it is called the first time, it will intialize NSS.  Once the NSS
261 * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
262 * if it is called again.
263 */
264KMF_RETURN
265NSS_ConfigureKeystore(KMF_HANDLE_T handle,
266	int numattr, KMF_ATTRIBUTE *attrlist)
267{
268	KMF_RETURN rv = KMF_OK;
269	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
270	char    *configdir;
271	char    *certPrefix;
272	char    *keyPrefix;
273	char    *secModName;
274
275	configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
276	certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
277	keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
278	secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
279
280	(void) mutex_lock(&init_lock);
281	if (nss_initialized == 0) {
282		SECStatus err;
283
284		(void) mutex_unlock(&init_lock);
285		err = Init_NSS_DBs(configdir, certPrefix,
286		    keyPrefix, secModName);
287		if (err != SECSuccess) {
288			SET_ERROR(kmfh, err);
289			return (KMF_ERR_INTERNAL);
290		}
291	} else {
292		rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
293		(void) mutex_unlock(&init_lock);
294	}
295
296	return (rv);
297}
298
299/*
300 * This function sets up the slot to be used for other operations.
301 * This function is basically called by every NSS SPI function.
302 * For those functions that can only be performed in the internal slot, the
303 * boolean "internal_slot_only" argument needs to be TRUE.
304 * A slot pointer will be returned when this function is executed successfully.
305 */
306KMF_RETURN
307do_nss_init(void *handle, int numattr,
308	KMF_ATTRIBUTE *attrlist,
309	boolean_t internal_slot_only,
310	PK11SlotInfo **nss_slot)
311{
312	KMF_RETURN rv = KMF_OK;
313	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
314	char *slotlabel = NULL;
315
316	if (!nss_initialized)
317		return (KMF_ERR_PLUGIN_INIT);
318
319	slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
320	/*
321	 * NSS Is already initialized, but we need to find
322	 * the right slot.
323	 */
324	if (slotlabel == NULL ||
325	    strcmp(slotlabel, "internal") == 0) {
326		*nss_slot = PK11_GetInternalKeySlot();
327	} else if (internal_slot_only == TRUE)  {
328		rv = KMF_ERR_SLOTNAME;
329		goto end;
330	} else {
331		*nss_slot = PK11_FindSlotByName(slotlabel);
332	}
333
334	if (*nss_slot == NULL) {
335		SET_ERROR(kmfh, PORT_GetError());
336		rv = KMF_ERR_SLOTNAME;
337		goto end;
338	}
339
340	/*
341	 * If the token was not yet initialized, return an error.
342	 */
343	if (PK11_NeedUserInit(*nss_slot)) {
344		rv = KMF_ERR_UNINITIALIZED_TOKEN;
345	}
346
347end:
348	return (rv);
349}
350
351static KMF_RETURN
352nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
353{
354	kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
355	kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
356
357	kmf_cert->certificate.Length = nss_cert->derCert.len;
358
359	if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
360	    NULL) {
361		kmf_cert->certificate.Length = 0;
362		return (KMF_ERR_MEMORY);
363	}
364	(void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
365	    nss_cert->derCert.len);
366	if (nss_cert->nickname != NULL)
367		kmf_cert->kmf_private.label =
368		    (char *)strdup(nss_cert->nickname);
369	return (KMF_OK);
370}
371
372static KMF_RETURN
373nss_getcert_by_label(KMF_HANDLE *kmfh,
374	char *name, KMF_X509_DER_CERT *kmf_cert,
375	uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
376{
377	KMF_RETURN rv = KMF_OK;
378	CERTCertificate *nss_cert;
379	SECCertTimeValidity validity;
380
381	nss_cert = PK11_FindCertFromNickname(name, NULL);
382	if (nss_cert == NULL) {
383		*num_certs = 0;
384		SET_ERROR(kmfh, PORT_GetError());
385		*num_certs = 0;
386		return (KMF_ERR_CERT_NOT_FOUND);
387	} else {
388		*num_certs = 1;
389	}
390
391	switch (find_criteria) {
392	case KMF_ALL_CERTS:
393		break;
394	case KMF_NONEXPIRED_CERTS:
395		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
396		    PR_FALSE);
397		if (validity != secCertTimeValid) {
398			/* this is an invalid cert, reject it */
399			*num_certs = 0;
400			CERT_DestroyCertificate(nss_cert);
401			return (KMF_OK);
402		}
403		break;
404	case KMF_EXPIRED_CERTS:
405		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
406		    PR_FALSE);
407		if (validity == secCertTimeValid) {
408			/* this is a valid cert, reject it in this case. */
409			*num_certs = 0;
410			CERT_DestroyCertificate(nss_cert);
411			return (KMF_OK);
412		}
413		break;
414	default:
415		return (KMF_ERR_BAD_PARAMETER);
416	}
417
418	if (kmf_cert != NULL)
419		rv = nss2kmf_cert(nss_cert, kmf_cert);
420
421	/* We copied the data we need, so cleanup the internal record */
422	CERT_DestroyCertificate(nss_cert);
423
424	if (rv != KMF_OK)
425		*num_certs = 0;
426
427	return (rv);
428}
429
430static KMF_RETURN
431nss_find_matching_certs(PK11SlotInfo *slot,
432	char *issuer, char *subject, KMF_BIGINT *serial,
433	CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
434{
435	KMF_RETURN rv = KMF_OK;
436	SECStatus ret;
437	CERTCertList *list;
438	CERTCertListNode *node;
439	KMF_X509_NAME issuerDN, subjectDN;
440	boolean_t findIssuer = FALSE;
441	boolean_t findSubject = FALSE;
442	boolean_t findSerial = FALSE;
443
444	if (issuer != NULL && strlen(issuer)) {
445		rv = kmf_dn_parser(issuer,  &issuerDN);
446		if (rv != KMF_OK)
447			return (rv);
448		findIssuer = TRUE;
449	}
450	if (subject != NULL && strlen(subject)) {
451		rv = kmf_dn_parser(subject, &subjectDN);
452		if (rv != KMF_OK)
453			return (rv);
454		findSubject = TRUE;
455	}
456	if (serial != 0 && serial->val != NULL && serial->len > 0)
457		findSerial = TRUE;
458
459	list = PK11_ListCertsInSlot(slot);
460	if (list) {
461		node = CERT_LIST_HEAD(list);
462		while (!CERT_LIST_END(node, list)) {
463			KMF_X509_NAME cmpDN;
464			KMF_DATA der;
465			boolean_t match;
466			CERTCertListNode *freenode;
467
468			if (findIssuer) {
469				der.Data = node->cert->derIssuer.data;
470				der.Length = node->cert->derIssuer.len;
471				rv = DerDecodeName(&der, &cmpDN);
472				if (rv == KMF_OK) {
473					match = !KMF_CompareRDNs(&issuerDN,
474					    &cmpDN);
475					kmf_free_dn(&cmpDN);
476					if (!match)
477						goto delete_and_cont;
478				} else {
479					goto delete_and_cont;
480				}
481			}
482			if (findSubject) {
483				der.Data = node->cert->derSubject.data;
484				der.Length = node->cert->derSubject.len;
485				rv = DerDecodeName(&der, &cmpDN);
486				if (rv == KMF_OK) {
487					match = !KMF_CompareRDNs(&subjectDN,
488					    &cmpDN);
489					kmf_free_dn(&cmpDN);
490					if (!match)
491						goto delete_and_cont;
492				} else {
493					goto delete_and_cont;
494				}
495			}
496			if (findSerial) {
497				SECItem *sernum;
498
499				sernum = &node->cert->serialNumber;
500
501				if (serial->len != sernum->len)
502					goto delete_and_cont;
503
504				if (memcmp(sernum->data, serial->val,
505				    serial->len))
506					goto delete_and_cont;
507			}
508
509			/* select the certs using find criteria */
510			switch (find_criteria) {
511			case KMF_ALL_CERTS:
512				break;
513			case KMF_NONEXPIRED_CERTS:
514				ret = CERT_CertTimesValid(node->cert);
515				if (ret == SECFailure) {
516					/* this is an invalid cert */
517					goto skip;
518				}
519				break;
520
521			case KMF_EXPIRED_CERTS:
522				ret = CERT_CertTimesValid(node->cert);
523				if (ret != SECFailure) {
524					/* this is a valid cert */
525					goto skip;
526				}
527				break;
528			}
529skip:
530			node = CERT_LIST_NEXT(node);
531			continue;
532delete_and_cont:
533			freenode = node;
534			node = CERT_LIST_NEXT(node);
535			CERT_RemoveCertListNode(freenode);
536		}
537	}
538
539	if (rv == KMF_OK && certlist != NULL) {
540		*certlist = list;
541	} else {
542		CERT_DestroyCertList(list);
543	}
544	return (rv);
545}
546
547static KMF_RETURN
548convertCertList(void *kmfhandle,
549	CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
550	uint32_t *numcerts)
551{
552	KMF_RETURN rv = KMF_OK;
553	CERTCertListNode *node;
554	uint32_t maxcerts = *numcerts;
555
556	maxcerts = *numcerts;
557	if (maxcerts == 0)
558		maxcerts = 0xFFFFFFFF;
559
560	*numcerts = 0;
561
562	/*
563	 * Don't copy more certs than the caller wanted.
564	 */
565	for (node = CERT_LIST_HEAD(nsscerts);
566	    !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
567	    (*numcerts) < maxcerts;
568	    node = CERT_LIST_NEXT(node), (*numcerts)++) {
569		if (kmfcerts != NULL)
570			rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
571	}
572
573	/*
574	 * If we failed, delete any certs allocated so far.
575	 */
576	if (rv != KMF_OK) {
577		int i;
578		for (i = 0; i < *numcerts; i++)
579			kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
580
581		*numcerts = 0;
582	}
583	return (rv);
584}
585
586KMF_RETURN
587NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
588{
589	KMF_RETURN rv = KMF_OK;
590	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
591	PK11SlotInfo *nss_slot = NULL;
592	CERTCertList *certlist = NULL;
593	uint32_t maxcerts;
594	uint32_t *num_certs;
595	KMF_X509_DER_CERT *kmfcerts = NULL;
596	char *certlabel = NULL;
597	char *issuer = NULL;
598	char *subject = NULL;
599	KMF_BIGINT *serial = NULL;
600	KMF_CERT_VALIDITY  validity;
601
602	if (handle == NULL || attrlist == NULL || numattr == 0) {
603		return (KMF_ERR_BAD_PARAMETER);
604	}
605	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
606	if (rv != KMF_OK)
607		return (rv);
608
609	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
610	if (num_certs == NULL)
611		return (KMF_ERR_BAD_PARAMETER);
612
613	maxcerts = *num_certs;
614	if (maxcerts == 0)
615		maxcerts = 0xFFFFFFFF;
616	*num_certs = 0;
617
618	/* Get the optional returned certificate list  */
619	kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
620
621	/* Get optional search criteria attributes */
622	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
623	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
624	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
625	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
626
627	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
628	    &validity, NULL);
629	if (rv != KMF_OK) {
630		validity = KMF_ALL_CERTS;
631		rv = KMF_OK;
632	}
633
634	if (certlabel != NULL) {
635		/* This will only find 1 certificate */
636		rv = nss_getcert_by_label(kmfh,	certlabel, kmfcerts, num_certs,
637		    validity);
638	} else {
639		/*
640		 * Build a list of matching certs.
641		 */
642		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
643		    &certlist, validity);
644
645		/*
646		 * If the caller supplied a pointer to storage for
647		 * a list of certs, convert up to 'maxcerts' of the
648		 * matching certs.
649		 */
650		if (rv == KMF_OK && certlist != NULL) {
651			rv = convertCertList(handle, certlist, kmfcerts,
652			    &maxcerts);
653			CERT_DestroyCertList(certlist);
654			if (rv == KMF_OK)
655				*num_certs = maxcerts;
656		}
657	}
658
659	if (nss_slot != NULL) {
660		PK11_FreeSlot(nss_slot);
661	}
662
663	if (rv == KMF_OK && *num_certs == 0)
664		rv = KMF_ERR_CERT_NOT_FOUND;
665
666	return (rv);
667}
668
669void
670/*ARGSUSED*/
671NSS_FreeKMFCert(KMF_HANDLE_T handle,
672	KMF_X509_DER_CERT *kmf_cert)
673{
674	if (kmf_cert != NULL) {
675		if (kmf_cert->certificate.Data != NULL) {
676			free(kmf_cert->certificate.Data);
677			kmf_cert->certificate.Data = NULL;
678			kmf_cert->certificate.Length = 0;
679		}
680		if (kmf_cert->kmf_private.label != NULL) {
681			free(kmf_cert->kmf_private.label);
682			kmf_cert->kmf_private.label = NULL;
683		}
684	}
685}
686
687
688KMF_RETURN
689NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
690{
691	KMF_RETURN rv = KMF_OK;
692	int nssrv;
693	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
694	CERTCertificate *cert = NULL;
695	PK11SlotInfo *nss_slot = NULL;
696	char *certlabel = NULL;
697	char *issuer = NULL;
698	char *subject = NULL;
699	KMF_BIGINT *serial = NULL;
700	KMF_CERT_VALIDITY  validity;
701
702	if (handle == NULL || attrlist == NULL || numattr == 0) {
703		return (KMF_ERR_BAD_PARAMETER);
704	}
705	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
706	if (rv != KMF_OK)
707		return (rv);
708
709	/* Get the search criteria attributes.  They are all optional. */
710	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
711	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
712	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
713	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
714
715	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
716	    &validity, NULL);
717	if (rv != KMF_OK) {
718		validity = KMF_ALL_CERTS;
719		rv = KMF_OK;
720	}
721
722	/* Start finding the matched certificates and delete them. */
723	if (certlabel != NULL) {
724		cert = PK11_FindCertFromNickname(certlabel, NULL);
725		if (cert == NULL) {
726			return (KMF_ERR_CERT_NOT_FOUND);
727		}
728
729		switch (validity) {
730		case KMF_ALL_CERTS:
731			break;
732		case KMF_NONEXPIRED_CERTS:
733			nssrv = CERT_CertTimesValid(cert);
734			if (nssrv == SECFailure) {
735				/* this is an invalid cert - skip it */
736				goto out;
737			}
738			break;
739		case KMF_EXPIRED_CERTS:
740			nssrv = CERT_CertTimesValid(cert);
741			if (nssrv != SECFailure) {
742				/* this is a valid cert - skip it */
743				goto out;
744			}
745			break;
746		}
747		/* delete it from database */
748		nssrv = SEC_DeletePermCertificate(cert);
749		if (nssrv) {
750			SET_ERROR(kmfh, nssrv);
751			rv = KMF_ERR_INTERNAL;
752		}
753	} else {
754		CERTCertListNode *node;
755		CERTCertList *certlist = NULL;
756
757		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
758		    &certlist, validity);
759
760		for (node = CERT_LIST_HEAD(certlist);
761		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
762		    node = CERT_LIST_NEXT(node)) {
763
764			nssrv = SEC_DeletePermCertificate(node->cert);
765			if (nssrv) {
766				SET_ERROR(kmfh, nssrv);
767				rv = KMF_ERR_INTERNAL;
768			}
769		}
770
771		if (rv == KMF_OK && certlist != NULL) {
772			CERT_DestroyCertList(certlist);
773		} else if (rv == KMF_OK && certlist == NULL) {
774			rv = KMF_ERR_CERT_NOT_FOUND;
775		}
776	}
777out:
778	if (nss_slot != NULL) {
779		PK11_FreeSlot(nss_slot);
780	}
781
782	if (cert != NULL) {
783		CERT_DestroyCertificate(cert);
784	}
785
786	return (rv);
787}
788
789static void
790InitRandom(char *filename)
791{
792	char buf[2048];
793	int fd;
794	PRInt32 count;
795
796	fd = open(filename, O_RDONLY);
797	if (!fd)
798		return;
799
800	count = read(fd, buf, sizeof (buf));
801	if (count > 0) {
802		PK11_RandomUpdate(buf, count);
803	}
804
805	(void) close(fd);
806}
807
808KMF_RETURN
809NSS_CreateKeypair(KMF_HANDLE_T handle,
810	int numattr, KMF_ATTRIBUTE *attrlist)
811{
812	KMF_RETURN rv = KMF_OK;
813	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
814	PK11RSAGenParams rsaparams;
815	void *nssparams;
816	CK_MECHANISM_TYPE mechanism;
817	ulong_t publicExponent = 0x010001;
818	PK11SlotInfo *nss_slot = NULL;
819	SECKEYPrivateKey *NSSprivkey = NULL;
820	SECKEYPublicKey *NSSpubkey = NULL;
821	PQGParams *pqgParams = NULL;
822	KMF_CREDENTIAL cred;
823	boolean_t storekey = TRUE;
824	uint32_t keylen = 1024, len;
825	uint32_t keylen_size = sizeof (uint32_t);
826	KMF_KEY_ALG keytype = KMF_RSA;
827	KMF_KEY_HANDLE *pubkey = NULL;
828	KMF_KEY_HANDLE *privkey = NULL;
829	char *keylabel = NULL;
830
831	if (handle == NULL || attrlist == NULL || numattr == 0) {
832		return (KMF_ERR_BAD_PARAMETER);
833	}
834	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
835	if (rv != KMF_OK) {
836		return (rv);
837	}
838
839	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
840	    (void *)&cred, NULL);
841	if (rv != KMF_OK)
842		return (rv);
843
844	rv = nss_authenticate(handle, nss_slot, &cred);
845	if (rv != KMF_OK) {
846		return (rv);
847	}
848
849	/* "storekey" is optional. Default is TRUE */
850	(void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
851	    &storekey, NULL);
852
853	/* keytype is optional.  KMF_RSA is default */
854	(void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
855	    (void *)&keytype, NULL);
856
857	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
858	    &keylen, &keylen_size);
859	if (rv == KMF_ERR_ATTR_NOT_FOUND)
860		/* Default keylen = 1024 */
861		rv = KMF_OK;
862	else if (rv != KMF_OK)
863		return (KMF_ERR_BAD_PARAMETER);
864
865	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
866	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
867	if (pubkey == NULL || privkey == NULL)
868		return (KMF_ERR_BAD_PARAMETER);
869
870	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
871	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
872
873	rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,	NULL, &len);
874	if (rv == KMF_OK && len > 0) {
875		keylabel = malloc(len + 1);
876		if (keylabel == NULL)
877			return (KMF_ERR_MEMORY);
878		/* Now fill in the label value */
879		(void) memset(keylabel, 0, len + 1);
880		rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
881		    keylabel, NULL);
882		if (rv != KMF_OK) {
883			free(keylabel);
884			goto cleanup;
885		}
886	}
887
888	/* Get some random bits */
889	InitRandom("/dev/urandom");
890	if (keytype == KMF_RSA) {
891		KMF_BIGINT rsaexp;
892
893		rsaparams.keySizeInBits = keylen;
894		/*
895		 * NSS only allows for a 4 byte exponent.
896		 * Ignore the exponent parameter if it is too big.
897		 */
898		if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
899		    &rsaexp, NULL)) == KMF_OK) {
900			if (rsaexp.len > 0 &&
901			    rsaexp.len <= sizeof (publicExponent) &&
902			    rsaexp.val != NULL) {
903				(void) memcpy(&publicExponent, rsaexp.val,
904				    rsaexp.len);
905			}
906		}
907		rsaparams.pe = publicExponent;
908		mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
909		nssparams = &rsaparams;
910	} else if (keytype == KMF_DSA) {
911		PQGVerify *pqgVerify = NULL;
912		int ks;
913		SECStatus	nssrv, passed;
914
915		mechanism = CKM_DSA_KEY_PAIR_GEN;
916
917		ks = PQG_PBITS_TO_INDEX(keylen);
918		nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
919		if (nssrv != SECSuccess) {
920			SET_ERROR(kmfh, rv);
921			PK11_PQG_DestroyVerify(pqgVerify);
922			rv = KMF_ERR_KEYGEN_FAILED;
923			goto cleanup;
924		}
925
926		nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
927		if (nssrv != SECSuccess || passed != SECSuccess) {
928			SET_ERROR(kmfh, rv);
929			rv = KMF_ERR_KEYGEN_FAILED;
930		}
931
932		PK11_PQG_DestroyVerify(pqgVerify);
933
934		if (rv != KMF_OK) {
935			SET_ERROR(kmfh, PORT_GetError());
936			goto cleanup;
937		}
938
939		nssparams = pqgParams;
940	} else {
941		rv = KMF_ERR_BAD_PARAMETER;
942		goto cleanup;
943	}
944
945	NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
946	    &NSSpubkey,
947	    storekey, /* isPermanent */
948	    PR_TRUE, /* isSensitive */
949	    (void *)cred.cred);
950
951	if (NSSprivkey == NULL || NSSpubkey == NULL) {
952		SET_ERROR(kmfh, PORT_GetError());
953		rv = KMF_ERR_KEYGEN_FAILED;
954	} else {
955		if (keylabel != NULL && strlen(keylabel)) {
956			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
957			    keylabel);
958			(void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
959		}
960		/* Now, convert it to a KMF_KEY object for the framework */
961		privkey->kstype = KMF_KEYSTORE_NSS;
962		privkey->keyalg = keytype;
963		privkey->keyclass = KMF_ASYM_PRI;
964		privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
965		privkey->keyp = (void *)NSSprivkey;
966
967		pubkey->kstype = KMF_KEYSTORE_NSS;
968		pubkey->keyalg = keytype;
969		pubkey->keyp = (void *)NSSpubkey;
970		pubkey->keyclass = KMF_ASYM_PUB;
971		pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
972
973		rv = KMF_OK;
974	}
975cleanup:
976	if (rv != KMF_OK) {
977		if (NSSpubkey)
978			PK11_DeleteTokenPublicKey(NSSpubkey);
979		if (NSSprivkey)
980			PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
981
982		privkey->keyp = NULL;
983		pubkey->keyp = NULL;
984	}
985
986	if (keylabel)
987		free(keylabel);
988
989	if (pqgParams != NULL)
990		PK11_PQG_DestroyParams(pqgParams);
991
992	if (nss_slot != NULL)
993		PK11_FreeSlot(nss_slot);
994
995	return (rv);
996}
997
998KMF_RETURN
999NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1000    KMF_OID *AlgOID, KMF_DATA *tobesigned,
1001    KMF_DATA *output)
1002{
1003	KMF_RETURN		ret = KMF_OK;
1004	KMF_ALGORITHM_INDEX	AlgId;
1005	SECOidTag		signAlgTag;
1006	SECKEYPrivateKey	*NSSprivkey = NULL;
1007	SECStatus		rv;
1008	SECItem			signed_data;
1009	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1010
1011	signed_data.data = 0;
1012	if (key == NULL || AlgOID == NULL ||
1013	    tobesigned == NULL || output == NULL ||
1014	    tobesigned->Data == NULL ||
1015	    output->Data == NULL)
1016		return (KMF_ERR_BAD_PARAMETER);
1017
1018	/* Map the OID to a NSS algorithm */
1019	AlgId = x509_algoid_to_algid(AlgOID);
1020	if (AlgId == KMF_ALGID_NONE)
1021		return (KMF_ERR_BAD_PARAMETER);
1022
1023	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1024
1025	if (AlgId == KMF_ALGID_MD5WithRSA)
1026		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1027	else if (AlgId == KMF_ALGID_MD2WithRSA)
1028		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1029	else if (AlgId == KMF_ALGID_SHA1WithRSA)
1030		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1031	else if (AlgId == KMF_ALGID_SHA1WithDSA)
1032		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1033	else
1034		return (KMF_ERR_BAD_PARAMETER);
1035
1036	rv = SEC_SignData(&signed_data, tobesigned->Data,
1037	    tobesigned->Length, NSSprivkey, signAlgTag);
1038
1039	if (rv != 0) {
1040		SET_ERROR(kmfh, rv);
1041		return (KMF_ERR_INTERNAL);
1042	}
1043
1044	if (signed_data.len <= output->Length) {
1045		(void) memcpy(output->Data, signed_data.data, signed_data.len);
1046		output->Length = signed_data.len;
1047	} else {
1048		output->Length = 0;
1049		ret = KMF_ERR_BAD_PARAMETER;
1050	}
1051	free(signed_data.data);
1052
1053	return (ret);
1054}
1055
1056KMF_RETURN
1057NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1058	KMF_DATA *encoded)
1059{
1060	KMF_RETURN ret = KMF_OK;
1061	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1062	SECItem *rvitem;
1063	CERTSubjectPublicKeyInfo *spki = NULL;
1064
1065	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1066		return (KMF_ERR_BAD_PARAMETER);
1067
1068	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1069	if (spki == NULL) {
1070		SET_ERROR(kmfh, PORT_GetError());
1071		return (KMF_ERR_MEMORY);
1072	}
1073
1074	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1075	    CERT_SubjectPublicKeyInfoTemplate);
1076	if (rvitem != NULL) {
1077		encoded->Data = malloc(rvitem->len);
1078		if (encoded->Data == NULL) {
1079			ret = KMF_ERR_MEMORY;
1080		} else {
1081			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1082			encoded->Length = rvitem->len;
1083		}
1084		SECITEM_FreeItem(rvitem, TRUE);
1085	} else {
1086		SET_ERROR(kmfh, PORT_GetError());
1087		encoded->Data = NULL;
1088		encoded->Length = 0;
1089		ret = KMF_ERR_ENCODING;
1090	}
1091	SECKEY_DestroySubjectPublicKeyInfo(spki);
1092
1093	return (ret);
1094}
1095
1096KMF_RETURN
1097NSS_DeleteKey(KMF_HANDLE_T handle,
1098	int numattr, KMF_ATTRIBUTE *attrlist)
1099{
1100	KMF_RETURN rv = KMF_OK;
1101	PK11SlotInfo *nss_slot = NULL;
1102	KMF_KEY_HANDLE *key;
1103	KMF_CREDENTIAL cred;
1104	boolean_t delete_token = B_TRUE;
1105
1106	if (handle == NULL || attrlist == NULL || numattr == 0) {
1107		return (KMF_ERR_BAD_PARAMETER);
1108	}
1109	/*
1110	 * "delete_token" means to clear it from the token storage as well
1111	 * as from memory.
1112	 */
1113	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1114	if (key == NULL || key->keyp == NULL)
1115		return (KMF_ERR_BAD_PARAMETER);
1116
1117	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1118	    (void *)&delete_token, NULL);
1119	if (rv != KMF_OK)
1120		/* "delete_token" is optional. Default is TRUE */
1121		rv = KMF_OK;
1122
1123	if (delete_token) {
1124		SECStatus nssrv = SECSuccess;
1125		if (key->keyclass != KMF_ASYM_PUB &&
1126		    key->keyclass != KMF_ASYM_PRI &&
1127		    key->keyclass != KMF_SYMMETRIC)
1128			return (KMF_ERR_BAD_KEY_CLASS);
1129
1130		rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1131		if (rv != KMF_OK) {
1132			return (rv);
1133		}
1134
1135		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1136		    (void *)&cred, NULL);
1137		if (rv != KMF_OK)
1138			return (KMF_ERR_BAD_PARAMETER);
1139
1140		rv = nss_authenticate(handle, nss_slot, &cred);
1141		if (rv != KMF_OK) {
1142			return (rv);
1143		}
1144
1145		if (key->keyclass == KMF_ASYM_PUB) {
1146			nssrv = PK11_DeleteTokenPublicKey(
1147			    (SECKEYPublicKey *)key->keyp);
1148		} else if (key->keyclass == KMF_ASYM_PRI) {
1149			nssrv = PK11_DeleteTokenPrivateKey(
1150			    (SECKEYPrivateKey *)key->keyp, PR_TRUE);
1151		} else if (key->keyclass == KMF_SYMMETRIC) {
1152			nssrv = PK11_DeleteTokenSymKey(
1153			    (PK11SymKey *) key->keyp);
1154			if (nssrv == SECSuccess)
1155				PK11_FreeSymKey((PK11SymKey *) key->keyp);
1156		}
1157		if (nssrv != SECSuccess) {
1158			SET_ERROR(handle, PORT_GetError());
1159			rv = KMF_ERR_INTERNAL;
1160		}
1161	} else {
1162		if (key->keyclass == KMF_ASYM_PUB) {
1163			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1164		} else if (key->keyclass == KMF_ASYM_PRI) {
1165			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1166		} else if (key->keyclass == KMF_SYMMETRIC) {
1167			PK11_FreeSymKey((PK11SymKey *) key->keyp);
1168		} else {
1169			return (KMF_ERR_BAD_KEY_CLASS);
1170		}
1171	}
1172	key->keyp = NULL;
1173
1174	return (rv);
1175}
1176
1177KMF_RETURN
1178NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1179{
1180	KMF_RETURN ret = KMF_OK;
1181	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1182	char *str;
1183
1184	/* Get the error string in the default language */
1185	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1186
1187	if (str != NULL) {
1188		*msgstr = (char *)strdup(str);
1189		if ((*msgstr) == NULL)
1190			ret = KMF_ERR_MEMORY;
1191	} else {
1192		*msgstr = NULL;
1193	}
1194
1195	return (ret);
1196}
1197
1198KMF_RETURN
1199NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1200{
1201	KMF_RETURN rv = KMF_OK;
1202	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1203	PK11SlotInfo *nss_slot = NULL;
1204	KMF_CREDENTIAL cred;
1205	KMF_KEY_HANDLE *key = NULL;
1206	KMF_DATA *cert = NULL;
1207	CERTCertificate *nss_cert = NULL;
1208	SECKEYPrivateKey* privkey = NULL;
1209
1210	if (handle == NULL || attrlist == NULL || numattr == 0) {
1211		return (KMF_ERR_BAD_PARAMETER);
1212	}
1213
1214	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1215	if (rv != KMF_OK)
1216		return (rv);
1217
1218	/* Get the credential */
1219	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1220	    (void *)&cred, NULL);
1221	if (rv != KMF_OK)
1222		return (KMF_ERR_BAD_PARAMETER);
1223	rv = nss_authenticate(handle, nss_slot, &cred);
1224	if (rv != KMF_OK)
1225		return (rv);
1226
1227	/* Get the key handle */
1228	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1229	if (key == NULL)
1230		return (KMF_ERR_BAD_PARAMETER);
1231
1232	/* Get the cert data and decode it */
1233	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1234	if (cert == NULL || cert->Data == NULL)
1235		return (KMF_ERR_BAD_PARAMETER);
1236
1237	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
1238	    cert->Length);
1239	if (nss_cert == NULL) {
1240		SET_ERROR(kmfh, PORT_GetError());
1241		return (KMF_ERR_BAD_CERT_FORMAT);
1242	}
1243
1244	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1245	if (privkey == NULL) {
1246		SET_ERROR(kmfh, PORT_GetError());
1247		return (KMF_ERR_KEY_NOT_FOUND);
1248	}
1249
1250	key->kstype = KMF_KEYSTORE_NSS;
1251	key->keyclass = KMF_ASYM_PRI;
1252	key->keyp = (void *)privkey;
1253	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1254
1255	CERT_DestroyCertificate(nss_cert);
1256
1257	return (KMF_OK);
1258}
1259
1260
1261KMF_RETURN
1262NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1263	KMF_OID *AlgOID, KMF_DATA *ciphertext,
1264	KMF_DATA *output)
1265{
1266	KMF_RETURN		ret = KMF_OK;
1267	SECKEYPrivateKey	*NSSprivkey = NULL;
1268	SECStatus		rv;
1269	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1270	unsigned int in_len = 0, out_len = 0;
1271	unsigned int total_decrypted = 0, modulus_len = 0;
1272	uint8_t *in_data, *out_data;
1273	int i, blocks;
1274
1275	if (key == NULL || AlgOID == NULL ||
1276	    ciphertext == NULL || output == NULL ||
1277	    ciphertext->Data == NULL ||
1278	    output->Data == NULL)
1279		return (KMF_ERR_BAD_PARAMETER);
1280
1281	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1282	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1283
1284	blocks = ciphertext->Length/modulus_len;
1285	out_data = output->Data;
1286	in_data = ciphertext->Data;
1287	out_len = modulus_len - 11;
1288	in_len = modulus_len;
1289
1290	for (i = 0; i < blocks; i++) {
1291		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1292		    &out_len, ciphertext->Length, in_data, in_len);
1293
1294		if (rv != 0) {
1295			SET_ERROR(kmfh, rv);
1296			return (KMF_ERR_INTERNAL);
1297		}
1298
1299		out_data += out_len;
1300		total_decrypted += out_len;
1301		in_data += in_len;
1302	}
1303
1304	output->Length = total_decrypted;
1305
1306	return (ret);
1307}
1308
1309static KMF_KEY_ALG
1310pk11keytype2kmf(CK_KEY_TYPE type)
1311{
1312	switch (type) {
1313	case CKK_RSA:
1314		return (KMF_RSA);
1315	case CKK_DSA:
1316		return (KMF_RSA);
1317	case CKK_AES:
1318		return (KMF_AES);
1319	case CKK_RC4:
1320		return (KMF_RC4);
1321	case CKK_DES:
1322		return (KMF_DES);
1323	case CKK_DES3:
1324		return (KMF_DES3);
1325	default:
1326		/* not supported */
1327		return (KMF_KEYALG_NONE);
1328	}
1329}
1330
1331KMF_RETURN
1332NSS_FindKey(KMF_HANDLE_T handle,
1333	int numattr, KMF_ATTRIBUTE *attrlist)
1334{
1335	KMF_RETURN rv;
1336	SECKEYPrivateKeyList *prilist;
1337	SECKEYPrivateKeyListNode *prinode;
1338	SECKEYPublicKeyList *publist;
1339	SECKEYPublicKeyListNode *pubnode;
1340	PK11SlotInfo *nss_slot = NULL;
1341	PK11SymKey *symlist = NULL;
1342	int count;
1343	uint32_t maxkeys;
1344	KMF_KEY_HANDLE *keys;
1345	uint32_t *numkeys;
1346	KMF_CREDENTIAL cred;
1347	KMF_KEY_CLASS keyclass;
1348	char *findLabel;
1349	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
1350
1351	if (handle == NULL || attrlist == NULL || numattr == 0) {
1352		return (KMF_ERR_BAD_PARAMETER);
1353	}
1354
1355	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1356	if (numkeys == NULL)
1357		return (KMF_ERR_BAD_PARAMETER);
1358
1359	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1360	if (rv != KMF_OK) {
1361		return (rv);
1362	}
1363
1364	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1365	    (void *)&cred, NULL);
1366	if (rv != KMF_OK)
1367		return (KMF_ERR_BAD_PARAMETER);
1368
1369	rv = nss_authenticate(handle, nss_slot, &cred);
1370	if (rv != KMF_OK) {
1371		return (rv);
1372	}
1373
1374	maxkeys = *numkeys;
1375	if (maxkeys == 0)
1376		maxkeys = 0xFFFFFFFF;
1377	*numkeys = 0;
1378
1379	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
1380	    (void *)&keyclass, NULL);
1381	if (rv != KMF_OK)
1382		return (KMF_ERR_BAD_PARAMETER);
1383
1384	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1385
1386	if (keyclass == KMF_ASYM_PUB) {
1387		publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
1388		if (publist == NULL) {
1389			rv = KMF_ERR_KEY_NOT_FOUND;
1390			goto cleanup;
1391		}
1392	} else if (keyclass == KMF_ASYM_PRI) {
1393		prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
1394		if (prilist == NULL) {
1395			rv = KMF_ERR_KEY_NOT_FOUND;
1396			goto cleanup;
1397		}
1398	} else if (keyclass == KMF_SYMMETRIC) {
1399		symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
1400		if (symlist == NULL) {
1401			rv = KMF_ERR_KEY_NOT_FOUND;
1402			goto cleanup;
1403		}
1404	} else {
1405		rv = KMF_ERR_BAD_KEY_CLASS;
1406		goto cleanup;
1407	}
1408
1409	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1410	/* it is okay to have "keys" contains NULL */
1411
1412	if (keyclass == KMF_ASYM_PUB) {
1413		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1414		    !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
1415		    pubnode = PUBKEY_LIST_NEXT(pubnode), count++) {
1416			if (keys != NULL) {
1417				keys[count].kstype = KMF_KEYSTORE_NSS;
1418				keys[count].keyclass = KMF_ASYM_PUB;
1419				keys[count].keyp = (void *)pubnode->key;
1420				keys[count].keylabel =
1421				    PK11_GetPublicKeyNickname(pubnode->key);
1422
1423				if (pubnode->key->keyType == rsaKey)
1424					keys[count].keyalg = KMF_RSA;
1425				else if (pubnode->key->keyType == dsaKey)
1426					keys[count].keyalg = KMF_DSA;
1427			}
1428		}
1429		*numkeys = count;
1430	} else if (keyclass == KMF_ASYM_PRI) {
1431		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1432		    !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
1433		    prinode = PRIVKEY_LIST_NEXT(prinode), count++) {
1434			if (keys != NULL) {
1435				keys[count].kstype = KMF_KEYSTORE_NSS;
1436				keys[count].keyclass = KMF_ASYM_PRI;
1437				keys[count].keyp = (void *)prinode->key;
1438				keys[count].keylabel =
1439				    PK11_GetPrivateKeyNickname(prinode->key);
1440
1441				if (prinode->key->keyType == rsaKey)
1442					keys[count].keyalg = KMF_RSA;
1443				else if (prinode->key->keyType == dsaKey)
1444					keys[count].keyalg = KMF_DSA;
1445			}
1446		}
1447		*numkeys = count;
1448	} else if (keyclass == KMF_SYMMETRIC) {
1449		count = 0;
1450		rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1451		    (void *)&keytype, NULL);
1452		if (rv != KMF_OK)
1453			rv = KMF_OK;
1454		while (symlist && count < maxkeys) {
1455			PK11SymKey *symkey = symlist;
1456			CK_KEY_TYPE type;
1457			KMF_KEY_ALG keyalg;
1458
1459			type = PK11_GetSymKeyType(symkey);
1460			keyalg = pk11keytype2kmf(type);
1461
1462			symlist = PK11_GetNextSymKey(symkey);
1463
1464			/*
1465			 * If keytype is specified in the searching parameter,
1466			 * check the keytype and skip the key if its keytype
1467			 * doesn't match.
1468			 */
1469			if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
1470				/* free that key since we arent using it */
1471				PK11_FreeSymKey(symkey);
1472				continue;
1473			}
1474
1475			if (keys != NULL) {
1476				keys[count].kstype = KMF_KEYSTORE_NSS;
1477				keys[count].keyclass = KMF_SYMMETRIC;
1478				keys[count].keyp = (void *) symkey;
1479				keys[count].keylabel =
1480				    PK11_GetSymKeyNickname(symkey);
1481				keys[count].keyalg = keyalg;
1482			} else {
1483				PK11_FreeSymKey(symkey);
1484			}
1485			count++;
1486		}
1487		/*
1488		 * Cleanup memory for unused keys.
1489		 */
1490		while (symlist != NULL) {
1491			PK11SymKey *symkey = symlist;
1492
1493			PK11_FreeSymKey(symkey);
1494			symlist = PK11_GetNextSymKey(symkey);
1495		}
1496		*numkeys = count;
1497	}
1498
1499cleanup:
1500	if (nss_slot != NULL) {
1501		PK11_FreeSlot(nss_slot);
1502	}
1503
1504	return (rv);
1505}
1506
1507static SECStatus
1508p12u_SwapUnicodeBytes(SECItem *uniItem)
1509{
1510	unsigned int i;
1511	unsigned char a;
1512	if ((uniItem == NULL) || (uniItem->len % 2)) {
1513		return (SECFailure);
1514		}
1515	for (i = 0; i < uniItem->len; i += 2) {
1516		a = uniItem->data[i];
1517		uniItem->data[i] = uniItem->data[i+1];
1518		uniItem->data[i+1] = a;
1519	}
1520	return (SECSuccess);
1521}
1522
1523static PRBool
1524p12u_ucs2_ascii_conversion_function(
1525	PRBool		toUnicode,
1526	unsigned char	*inBuf,
1527	unsigned int	inBufLen,
1528	unsigned char	*outBuf,
1529	unsigned int	maxOutBufLen,
1530	unsigned int	*outBufLen,
1531	PRBool		swapBytes)
1532{
1533	SECItem it = { 0 };
1534	SECItem *dup = NULL;
1535	PRBool ret;
1536
1537	it.data = inBuf;
1538	it.len = inBufLen;
1539	dup = SECITEM_DupItem(&it);
1540	/*
1541	 * If converting Unicode to ASCII, swap bytes before conversion
1542	 * as neccessary.
1543	 */
1544	if (!toUnicode && swapBytes) {
1545		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
1546			SECITEM_ZfreeItem(dup, PR_TRUE);
1547			return (PR_FALSE);
1548		}
1549	}
1550	/* Perform the conversion. */
1551	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
1552	    outBuf, maxOutBufLen, outBufLen);
1553	if (dup)
1554		SECITEM_ZfreeItem(dup, PR_TRUE);
1555
1556	return (ret);
1557}
1558
1559static PRBool
1560p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
1561{
1562	if (!p12ctx || !p12ctx->filename) {
1563		return (PR_FALSE);
1564	}
1565
1566	if (fileRead) {
1567		p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
1568	} else {
1569		p12ctx->file = PR_Open(p12ctx->filename,
1570		    PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
1571	}
1572
1573	if (!p12ctx->file) {
1574		p12ctx->error = PR_TRUE;
1575		return (PR_FALSE);
1576	}
1577
1578	return (PR_TRUE);
1579}
1580
1581static void
1582p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
1583{
1584	if (!ppCtx || !(*ppCtx)) {
1585		return;
1586	}
1587
1588	if ((*ppCtx)->file != NULL) {
1589		PR_Close((*ppCtx)->file);
1590	}
1591
1592	if ((*ppCtx)->filename != NULL) {
1593		if (removeFile) {
1594			PR_Delete((*ppCtx)->filename);
1595		}
1596		free((*ppCtx)->filename);
1597	}
1598
1599	free(*ppCtx);
1600	*ppCtx = NULL;
1601}
1602
1603static p12uContext *
1604p12u_InitContext(PRBool fileImport, char *filename)
1605{
1606	p12uContext *p12ctx;
1607
1608	p12ctx = PORT_ZNew(p12uContext);
1609	if (!p12ctx) {
1610		return (NULL);
1611	}
1612
1613	p12ctx->error = PR_FALSE;
1614	p12ctx->errorValue = 0;
1615	p12ctx->filename = strdup(filename);
1616
1617	if (!p12u_OpenFile(p12ctx, fileImport)) {
1618		p12u_DestroyContext(&p12ctx, PR_FALSE);
1619		return (NULL);
1620	}
1621
1622	return (p12ctx);
1623}
1624
1625static void
1626p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
1627{
1628	p12uContext *p12cxt = arg;
1629	int writeLen;
1630
1631	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
1632		return;
1633	}
1634
1635	if (p12cxt->file == NULL) {
1636		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1637		p12cxt->error = PR_TRUE;
1638		return;
1639	}
1640
1641	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
1642
1643	if (writeLen != (int)len) {
1644		PR_Close(p12cxt->file);
1645		free(p12cxt->filename);
1646		p12cxt->filename = NULL;
1647		p12cxt->file = NULL;
1648		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1649		p12cxt->error = PR_TRUE;
1650	}
1651}
1652
1653#define	HANDLE_NSS_ERROR(r) {\
1654	SET_ERROR(kmfh, PORT_GetError()); \
1655	rv = r; \
1656	goto out; }
1657
1658static KMF_RETURN
1659add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
1660	CERTCertificate *cert, SECItem *pwitem)
1661{
1662	KMF_RETURN rv = KMF_OK;
1663	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
1664
1665	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
1666	if (PK11_IsFIPS()) {
1667		certSafe = keySafe;
1668	} else {
1669		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
1670		    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
1671	}
1672
1673	if (!certSafe || !keySafe) {
1674		rv = KMF_ERR_INTERNAL;
1675		goto out;
1676	}
1677
1678	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
1679	    CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
1680	    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
1681	    != SECSuccess) {
1682		rv = KMF_ERR_INTERNAL;
1683	}
1684out:
1685	return (rv);
1686}
1687
1688KMF_RETURN
1689NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1690{
1691	KMF_RETURN rv;
1692	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
1693	SEC_PKCS12ExportContext *p12ecx = NULL;
1694	p12uContext *p12ctx = NULL;
1695	CERTCertList *certlist = NULL;
1696	CERTCertificate *nsscert = NULL;
1697	CERTCertListNode* node = NULL;
1698	PK11SlotInfo	*slot = NULL;
1699	SECItem pwitem = {NULL, 0};
1700	KMF_CREDENTIAL *cred = NULL;
1701	KMF_CREDENTIAL *p12cred = NULL;
1702	char *certlabel = NULL;
1703	char *issuer = NULL;
1704	char *subject = NULL;
1705	KMF_BIGINT *serial = NULL;
1706	char *filename = NULL;
1707
1708	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1709		return (KMF_ERR_BAD_PARAMETER);
1710	}
1711
1712	rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
1713	if (rv != KMF_OK)
1714		return (rv);
1715
1716	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1717	if (cred == NULL)
1718		return (KMF_ERR_BAD_PARAMETER);
1719
1720	rv = nss_authenticate(handle, slot, cred);
1721	if (rv != KMF_OK)
1722		return (rv);
1723
1724	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
1725	if (p12cred  == NULL)
1726		return (KMF_ERR_BAD_PARAMETER);
1727
1728	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
1729	    numattr);
1730	if (filename == NULL)
1731		return (KMF_ERR_BAD_PARAMETER);
1732
1733	/* Get optional search criteria attributes */
1734	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1735	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1736	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1737	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1738
1739	/*
1740	 * Find the certificate(s) first.
1741	 */
1742	if (certlabel != NULL) {
1743		nsscert = PK11_FindCertFromNickname(certlabel, NULL);
1744		if (nsscert == NULL) {
1745			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
1746		}
1747	} else {
1748		rv = nss_find_matching_certs(slot, issuer, subject, serial,
1749		    &certlist, 0);
1750
1751		if (rv == KMF_OK && certlist == NULL) {
1752			return (KMF_ERR_CERT_NOT_FOUND);
1753		}
1754		if (rv != KMF_OK)
1755			return (rv);
1756	}
1757
1758	/*
1759	 * The KMF_CREDENTIAL holds the password to use for
1760	 * encrypting the PKCS12 key information.
1761	 */
1762	pwitem.data = (uchar_t *)p12cred->cred;
1763	pwitem.len = p12cred->credlen;
1764
1765	p12ctx = p12u_InitContext(PR_FALSE, filename);
1766	if (!p12ctx) {
1767		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1768	}
1769
1770	PORT_SetUCS2_ASCIIConversionFunction(
1771	    p12u_ucs2_ascii_conversion_function);
1772
1773	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
1774	if (!p12ecx) {
1775		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1776	}
1777
1778	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
1779	    != SECSuccess) {
1780		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
1781	}
1782
1783	/*
1784	 * NSS actually supports storing a list of keys and certs
1785	 * in the PKCS#12 PDU.  Nice feature.
1786	 */
1787	if (certlist != NULL) {
1788		for (node = CERT_LIST_HEAD(certlist);
1789		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
1790		    node = CERT_LIST_NEXT(node)) {
1791			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
1792		}
1793	} else if (nsscert != NULL) {
1794		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
1795	}
1796
1797	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
1798	    != SECSuccess) {
1799		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
1800	}
1801out:
1802	if (nsscert)
1803		CERT_DestroyCertificate(nsscert);
1804
1805	if (certlist)
1806		CERT_DestroyCertList(certlist);
1807
1808	if (p12ctx)
1809		p12u_DestroyContext(&p12ctx, PR_FALSE);
1810
1811	if (p12ecx)
1812		SEC_PKCS12DestroyExportContext(p12ecx);
1813
1814	return (rv);
1815}
1816
1817#define	SETATTR(t, n, atype, value, size) \
1818	t[n].type = atype; \
1819	t[n].pValue = (CK_BYTE *)value; \
1820	t[n].ulValueLen = (CK_ULONG)size;
1821
1822KMF_RETURN
1823NSS_CreateSymKey(KMF_HANDLE_T handle,
1824	int numattr, KMF_ATTRIBUTE *attrlist)
1825{
1826	KMF_RETURN rv = KMF_OK;
1827	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1828	PK11SlotInfo *nss_slot = NULL;
1829	PK11SymKey *nsskey = NULL;
1830	CK_MECHANISM_TYPE keyType;
1831	SECStatus nssrv;
1832	int keySize;
1833	KMF_KEY_HANDLE *symkey;
1834	KMF_CREDENTIAL cred;
1835	uint32_t keylen;
1836	uint32_t keylen_size = sizeof (uint32_t);
1837	KMF_KEY_ALG keytype;
1838	char *keylabel = NULL;
1839
1840	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1841		return (KMF_ERR_BAD_PARAMETER);
1842	}
1843
1844	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1845	if (symkey == NULL)
1846		return (KMF_ERR_BAD_PARAMETER);
1847
1848	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
1849	    NULL);
1850	if (rv != KMF_OK)
1851		return (KMF_ERR_BAD_PARAMETER);
1852
1853	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
1854	    &keylen_size);
1855	if (rv == KMF_ERR_ATTR_NOT_FOUND &&
1856	    (keytype == KMF_DES || keytype == KMF_DES3))
1857		/* keylength is not required for DES and 3DES */
1858		rv = KMF_OK;
1859	if (rv != KMF_OK)
1860		return (KMF_ERR_BAD_PARAMETER);
1861
1862	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1863	if (keylabel == NULL)
1864		return (KMF_ERR_BAD_PARAMETER);
1865
1866	switch (keytype) {
1867	case KMF_AES:
1868		keyType = CKM_AES_KEY_GEN;
1869		keySize = keylen;
1870		if (keySize == 0 || (keySize % 8) != 0)
1871			return (KMF_ERR_BAD_KEY_SIZE);
1872		break;
1873	case KMF_RC4:
1874		keyType = CKM_RC4_KEY_GEN;
1875		keySize = keylen;
1876		if (keySize == 0 || (keySize % 8) != 0)
1877			return (KMF_ERR_BAD_KEY_SIZE);
1878		break;
1879	case KMF_DES:
1880		keyType = CKM_DES_KEY_GEN;
1881		keySize = 0; /* required by PK11_TokenKeyGen()  */
1882		break;
1883	case KMF_DES3:
1884		keyType = CKM_DES3_KEY_GEN;
1885		keySize = 0; /* required by PK11_TokenKeyGen() */
1886		break;
1887	case KMF_GENERIC_SECRET:
1888		keyType = CKM_GENERIC_SECRET_KEY_GEN;
1889		keySize = keylen;
1890		if (keySize == 0 || (keySize % 8) != 0)
1891			return (KMF_ERR_BAD_KEY_SIZE);
1892		break;
1893	default:
1894		rv = KMF_ERR_BAD_KEY_TYPE;
1895		goto out;
1896	}
1897
1898	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1899	if (rv != KMF_OK) {
1900		return (rv);
1901	}
1902
1903	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1904	    (void *)&cred, NULL);
1905	if (rv != KMF_OK)
1906		return (KMF_ERR_BAD_PARAMETER);
1907
1908	rv = nss_authenticate(handle, nss_slot, &cred);
1909	if (rv != KMF_OK) {
1910		return (rv);
1911	}
1912
1913	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize,  NULL,
1914	    PR_TRUE, (void *)cred.cred);
1915	if (nsskey == NULL) {
1916		SET_ERROR(kmfh, PORT_GetError());
1917		rv = KMF_ERR_KEYGEN_FAILED;
1918		goto out;
1919	}
1920
1921	nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
1922	if (nssrv != SECSuccess) {
1923		SET_ERROR(kmfh, PORT_GetError());
1924		rv = KMF_ERR_KEYGEN_FAILED;
1925		goto out;
1926	}
1927
1928	symkey->kstype = KMF_KEYSTORE_NSS;
1929	symkey->keyalg = keytype;
1930	symkey->keyclass = KMF_SYMMETRIC;
1931	symkey->israw = FALSE;
1932	symkey->keyp = (void *)nsskey;
1933
1934out:
1935	if (nss_slot != NULL)
1936		PK11_FreeSlot(nss_slot);
1937
1938	if (rv != KMF_OK && nsskey != NULL) {
1939		PK11_DeleteTokenSymKey(nsskey);
1940		PK11_FreeSymKey(nsskey);
1941	}
1942	return (rv);
1943}
1944
1945KMF_RETURN
1946NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
1947	KMF_RAW_SYM_KEY *rkey)
1948{
1949	KMF_RETURN rv = KMF_OK;
1950	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1951	SECItem *value = NULL;
1952	PK11SymKey *nsskey;
1953	SECStatus nss_rv;
1954
1955	if (kmfh == NULL)
1956		return (KMF_ERR_UNINITIALIZED);
1957
1958	if (symkey == NULL || rkey == NULL)
1959		return (KMF_ERR_BAD_PARAMETER);
1960	else if (symkey->keyclass != KMF_SYMMETRIC)
1961		return (KMF_ERR_BAD_KEY_CLASS);
1962
1963	if (symkey->israw) {
1964		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
1965
1966		if (rawkey == NULL ||
1967		    rawkey->rawdata.sym.keydata.val == NULL ||
1968		    rawkey->rawdata.sym.keydata.len == 0)
1969			return (KMF_ERR_BAD_KEYHANDLE);
1970
1971		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
1972		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
1973			return (KMF_ERR_MEMORY);
1974		(void) memcpy(rkey->keydata.val,
1975		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
1976	} else {
1977		nsskey = (PK11SymKey *)(symkey->keyp);
1978		if (nsskey == NULL)
1979			return (KMF_ERR_BAD_KEYHANDLE);
1980
1981		nss_rv = PK11_ExtractKeyValue(nsskey);
1982		if (nss_rv != SECSuccess) {
1983			SET_ERROR(kmfh, PORT_GetError());
1984			rv = KMF_ERR_GETKEYVALUE_FAILED;
1985			goto out;
1986		}
1987
1988		value = PK11_GetKeyData(nsskey);
1989		if (value == NULL) {
1990			SET_ERROR(kmfh, PORT_GetError());
1991			rv = KMF_ERR_GETKEYVALUE_FAILED;
1992			goto out;
1993		}
1994
1995		if (value->len == 0 || value->data == NULL) {
1996			rv = KMF_ERR_GETKEYVALUE_FAILED;
1997			goto out;
1998		}
1999
2000		rkey->keydata.val = malloc(value->len);
2001		if (rkey->keydata.val == NULL) {
2002			rv = KMF_ERR_MEMORY;
2003			goto out;
2004		}
2005		(void) memcpy(rkey->keydata.val, value->data, value->len);
2006		rkey->keydata.len = value->len;
2007		(void) memset(value->data, 0, value->len);
2008	}
2009out:
2010	if (value != NULL)
2011		SECITEM_FreeItem(value, PR_TRUE);
2012	return (rv);
2013}
2014
2015KMF_RETURN
2016NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2017{
2018	KMF_RETURN ret = KMF_OK;
2019	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2020	int rv;
2021	PK11SlotInfo *nss_slot = NULL;
2022	KMF_CREDENTIAL oldcred, newcred;
2023
2024	if (handle == NULL || attrlist == NULL || numattr == 0)
2025		return (KMF_ERR_BAD_PARAMETER);
2026
2027	ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2028	    (void *)&oldcred, NULL);
2029	if (ret != KMF_OK)
2030		return (KMF_ERR_BAD_PARAMETER);
2031	ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
2032	    (void *)&newcred, NULL);
2033	if (ret != KMF_OK)
2034		return (KMF_ERR_BAD_PARAMETER);
2035
2036	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2037	/* If it was uninitialized, set it */
2038	if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2039		rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
2040		if (rv != SECSuccess) {
2041			SET_ERROR(kmfh, PORT_GetError());
2042			ret = KMF_ERR_AUTH_FAILED;
2043		} else {
2044			ret = KMF_OK;
2045		}
2046	} else if (ret == KMF_OK) {
2047		ret = nss_authenticate(handle, nss_slot, &oldcred);
2048		if (ret != KMF_OK) {
2049			return (ret);
2050		}
2051		rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
2052		if (rv != SECSuccess) {
2053			SET_ERROR(kmfh, PORT_GetError());
2054			ret = KMF_ERR_AUTH_FAILED;
2055		}
2056	}
2057
2058	return (ret);
2059}
2060
2061KMF_RETURN
2062NSS_StoreKey(KMF_HANDLE_T handle,
2063	int numattr, KMF_ATTRIBUTE *attrlist)
2064{
2065	KMF_RETURN rv = KMF_OK;
2066	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2067	PK11SlotInfo *nss_slot = NULL;
2068	KMF_CREDENTIAL cred = {NULL, 0};
2069	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
2070	KMF_RAW_KEY_DATA *rawkey = NULL;
2071	char *keylabel = NULL;
2072	SECStatus ckrv = SECSuccess;
2073	SECItem nickname = {NULL, 0};
2074	CERTCertificate *nss_cert = NULL;
2075
2076	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2077		return (KMF_ERR_BAD_PARAMETER);
2078	}
2079
2080	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2081	if (rv != KMF_OK) {
2082		return (rv);
2083	}
2084
2085	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2086	    (void *)&cred, NULL);
2087	if (rv != KMF_OK)
2088		return (KMF_ERR_BAD_PARAMETER);
2089
2090	rv = nss_authenticate(handle, nss_slot, &cred);
2091	if (rv != KMF_OK) {
2092		return (rv);
2093	}
2094
2095	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2096	if (pubkey == NULL) {
2097		/* look for private key */
2098		prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
2099		    numattr);
2100		if (prikey == NULL)
2101			/* look for raw key */
2102			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
2103			    attrlist, numattr);
2104	}
2105
2106	/* If no keys were found, return error */
2107	if (pubkey == NULL && prikey == NULL && rawkey == NULL)
2108		return (KMF_ERR_ATTR_NOT_FOUND);
2109
2110	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2111	if (keylabel != NULL) {
2112		nickname.data = (uchar_t *)keylabel;
2113		nickname.len = strlen(keylabel);
2114	}
2115
2116	if (rawkey != NULL) {
2117		uchar_t ver = 0;
2118		SECKEYPrivateKeyInfo rpk;
2119		KMF_DATA derkey = {NULL, 0};
2120		KMF_DATA *cert;
2121
2122		cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2123		if (cert == NULL)
2124			return (rv);
2125		/*
2126		 * Decode the cert into an NSS CERT object so we can access the
2127		 * SPKI and KeyUsage data later.
2128		 */
2129		nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2130		    cert->Length);
2131
2132		if (nss_cert == NULL) {
2133			SET_ERROR(kmfh, PORT_GetError());
2134			rv = KMF_ERR_BAD_CERT_FORMAT;
2135			goto cleanup;
2136		}
2137
2138		(void) memset(&rpk, 0, sizeof (rpk));
2139		rpk.arena = NULL;
2140		rpk.version.type = siUnsignedInteger;
2141		rpk.version.data = &ver;
2142		rpk.version.len = 1;
2143		if (rawkey->keytype == KMF_RSA) {
2144			rv = DerEncodeRSAPrivateKey(&derkey,
2145			    &rawkey->rawdata.rsa);
2146			if (rv != KMF_OK)
2147				goto cleanup;
2148
2149		} else if (rawkey->keytype == KMF_DSA) {
2150			rv = DerEncodeDSAPrivateKey(&derkey,
2151			    &rawkey->rawdata.dsa);
2152			if (rv != KMF_OK)
2153				goto cleanup;
2154		}
2155		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2156		rpk.privateKey.data = derkey.Data;
2157		rpk.privateKey.len = derkey.Length;
2158		rpk.attributes = NULL;
2159
2160		ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
2161		    &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
2162		    TRUE, nss_cert->keyUsage, NULL);
2163		if (ckrv != CKR_OK) {
2164			SET_ERROR(kmfh, PORT_GetError());
2165			rv = KMF_ERR_INTERNAL;
2166		}
2167		kmf_free_data(&derkey);
2168	} else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
2169		CK_OBJECT_HANDLE pk;
2170		SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
2171
2172		pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
2173		if (pk == CK_INVALID_HANDLE) {
2174			SET_ERROR(kmfh, PORT_GetError());
2175			rv = KMF_ERR_INTERNAL;
2176		}
2177	} else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
2178		SECKEYPrivateKey *pk;
2179		SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
2180
2181		pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
2182		    PR_TRUE);
2183		if (pk == CK_INVALID_HANDLE) {
2184			SET_ERROR(kmfh, PORT_GetError());
2185			rv = KMF_ERR_INTERNAL;
2186		}
2187		/* We stored it, but don't need the handle anymore */
2188		SECKEY_DestroyPrivateKey(pk);
2189	}
2190
2191cleanup:
2192	if (nss_cert != NULL)
2193		CERT_DestroyCertificate(nss_cert);
2194	PK11_FreeSlot(nss_slot);
2195	return (rv);
2196}
2197
2198/*
2199 * This function is called by NSS_StoreCert() and NSS_ImportCert().
2200 * The "label" and "trust_flag" arguments can be NULL.
2201 */
2202static KMF_RETURN
2203store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
2204    char *label, char *trust_flag)
2205{
2206	KMF_RETURN ret = KMF_OK;
2207	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2208	SECStatus nss_rv;
2209	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2210	CERTCertificate *nss_cert = NULL;
2211	CERTCertTrust *nss_trust = NULL;
2212
2213	if (nss_slot == NULL || cert == NULL)
2214		return (KMF_ERR_BAD_PARAMETER);
2215
2216	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2217	    cert->Length);
2218	if (nss_cert == NULL) {
2219		SET_ERROR(kmfh, PORT_GetError());
2220		ret = KMF_ERR_BAD_CERT_FORMAT;
2221		goto out;
2222	}
2223
2224	/* Store the cert into the NSS database */
2225	nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
2226	    label, 0);
2227	if (nss_rv) {
2228		SET_ERROR(kmfh, nss_rv);
2229		ret = KMF_ERR_BAD_CERT_FORMAT;
2230		goto out;
2231	}
2232
2233	/* If trust_flag is NULL, then we are done */
2234	if (trust_flag == NULL)
2235		goto out;
2236
2237	nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
2238	if (nss_trust == NULL) {
2239		ret = KMF_ERR_MEMORY;
2240		goto out;
2241	}
2242
2243	nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
2244	if (nss_rv) {
2245		SET_ERROR(kmfh, nss_rv);
2246		ret = KMF_ERR_BAD_PARAMETER;
2247		goto out;
2248	}
2249
2250	nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
2251	if (nss_rv) {
2252		SET_ERROR(kmfh, nss_rv);
2253		ret = KMF_ERR_BAD_PARAMETER;
2254	}
2255
2256out:
2257	if (nss_cert != NULL) {
2258		CERT_DestroyCertificate(nss_cert);
2259	}
2260
2261	if (nss_trust != NULL) {
2262		free(nss_trust);
2263	}
2264
2265	return (ret);
2266}
2267
2268
2269KMF_RETURN
2270NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2271{
2272	KMF_RETURN ret = KMF_OK;
2273	PK11SlotInfo *nss_slot = NULL;
2274	KMF_DATA *cert = NULL;
2275	char *label = NULL;
2276	char *trust_flag = NULL;
2277
2278	if (handle == NULL || attrlist == NULL || numattr == 0) {
2279		return (KMF_ERR_BAD_PARAMETER);
2280	}
2281
2282	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2283	if (ret != KMF_OK)
2284		return (ret);
2285
2286	/* Get the cert data  */
2287	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2288	if (cert == NULL || cert->Data == NULL)
2289		return (KMF_ERR_BAD_PARAMETER);
2290
2291	/* The label attribute is optional */
2292	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2293
2294	/* The trustflag attriburte is optional */
2295	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2296
2297	ret = store_cert(handle, nss_slot, cert, label, trust_flag);
2298
2299out:
2300	if (nss_slot != NULL) {
2301		PK11_FreeSlot(nss_slot);
2302	}
2303
2304	return (ret);
2305}
2306
2307
2308KMF_RETURN
2309NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2310{
2311	KMF_RETURN ret = KMF_OK;
2312	PK11SlotInfo *nss_slot = NULL;
2313	KMF_DATA cert = {NULL, 0};
2314	KMF_DATA cert_der = {NULL, 0};
2315	KMF_DATA *cptr = NULL;
2316	KMF_ENCODE_FORMAT format;
2317	char *label = NULL;
2318	char *trust_flag = NULL;
2319	char *certfile = NULL;
2320
2321	if (handle == NULL || attrlist == NULL || numattr == 0) {
2322		return (KMF_ERR_BAD_PARAMETER);
2323	}
2324
2325	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2326	if (ret != KMF_OK)
2327		return (ret);
2328
2329	/* Get the input cert filename attribute */
2330	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2331	if (certfile == NULL)
2332		return (KMF_ERR_BAD_PARAMETER);
2333
2334	/* Check the cert file and auto-detect the file format of it. */
2335	ret = kmf_is_cert_file(handle, certfile, &format);
2336	if (ret != KMF_OK)
2337		return (ret);
2338
2339	ret = kmf_read_input_file(handle, certfile, &cert);
2340	if (ret != KMF_OK) {
2341		return (ret);
2342	}
2343
2344	/*
2345	 * If the imported cert is in PEM format, convert it to
2346	 * DER format in order to store it in NSS token.
2347	 */
2348	if (format == KMF_FORMAT_PEM) {
2349		int derlen;
2350		ret = kmf_pem_to_der(cert.Data, cert.Length,
2351		    &cert_der.Data, &derlen);
2352		if (ret != KMF_OK) {
2353			goto cleanup;
2354		}
2355		cert_der.Length = (size_t)derlen;
2356		cptr = &cert_der;
2357	} else {
2358		cptr = &cert;
2359	}
2360
2361	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2362	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2363	ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
2364
2365cleanup:
2366	if (format == KMF_FORMAT_PEM) {
2367		kmf_free_data(&cert_der);
2368	}
2369
2370	kmf_free_data(&cert);
2371
2372	return (ret);
2373}
2374
2375
2376KMF_RETURN
2377NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2378{
2379	KMF_RETURN ret = KMF_OK;
2380	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2381	PK11SlotInfo *nss_slot = NULL;
2382	CERTSignedCrl *nss_crl = NULL;
2383	KMF_ENCODE_FORMAT format;
2384	int importOptions;
2385	SECItem crlDER;
2386	KMF_DATA crl1;
2387	KMF_DATA crl2;
2388	char *crlfilename;
2389	boolean_t crlcheck = FALSE;
2390
2391	if (attrlist == NULL || numattr == 0) {
2392		return (KMF_ERR_BAD_PARAMETER);
2393	}
2394
2395	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2396	if (ret != KMF_OK) {
2397		return (ret);
2398	}
2399
2400	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
2401	    numattr);
2402	if (crlfilename == NULL)
2403		return (KMF_ERR_BAD_CRLFILE);
2404
2405	/*
2406	 * Check if the input CRL file is a valid CRL file and auto-detect
2407	 * the encoded format of the file.
2408	 */
2409	ret = kmf_is_crl_file(handle, crlfilename, &format);
2410	if (ret != KMF_OK)
2411		return (ret);
2412
2413	ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
2414	    &crlcheck, NULL);
2415	if (ret != KMF_OK)
2416		ret = KMF_OK; /* CRL_CHECK is optional */
2417
2418	/* set importOptions */
2419	if (crlcheck == B_FALSE) {
2420		importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
2421		    CRL_IMPORT_BYPASS_CHECKS;
2422	} else {
2423		importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
2424	}
2425
2426
2427	/* Read in the CRL file */
2428	crl1.Data = NULL;
2429	crl2.Data = NULL;
2430	ret = kmf_read_input_file(handle, crlfilename, &crl1);
2431	if (ret != KMF_OK) {
2432		return (ret);
2433	}
2434
2435	/* If the input CRL is in PEM format, convert it to DER first. */
2436	if (format == KMF_FORMAT_PEM) {
2437		int len;
2438		ret = kmf_pem_to_der(crl1.Data, crl1.Length,
2439		    &crl2.Data, &len);
2440		if (ret != KMF_OK) {
2441			goto out;
2442		}
2443		crl2.Length = (size_t)len;
2444	}
2445
2446	crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
2447	crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
2448
2449	nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
2450	    NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
2451
2452	if (nss_crl == NULL) {
2453		SET_ERROR(kmfh, PORT_GetError());
2454		ret = KMF_ERR_BAD_CRLFILE;
2455		goto out;
2456	}
2457
2458out:
2459	if (nss_slot != NULL) {
2460		PK11_FreeSlot(nss_slot);
2461	}
2462
2463	if (crl1.Data != NULL) {
2464		free(crl1.Data);
2465	}
2466
2467	if (crl2.Data != NULL) {
2468		free(crl2.Data);
2469	}
2470
2471	if (nss_crl != NULL) {
2472		SEC_DestroyCrl(nss_crl);
2473	}
2474
2475	return (ret);
2476}
2477
2478KMF_RETURN
2479NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2480{
2481	KMF_RETURN rv = KMF_OK;
2482	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2483	CERTSignedCrl *crl = NULL;
2484	CERTCertificate *cert = NULL;
2485	PK11SlotInfo *nss_slot = NULL;
2486	CERTCrlHeadNode *crlList = NULL;
2487	CERTCrlNode *crlNode = NULL;
2488	PRArenaPool *arena = NULL;
2489	CERTName *name = NULL;
2490	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2491	char *issuername, *subjectname;
2492
2493	/* check params */
2494	if (numattr == 0 || attrlist == NULL) {
2495		return (KMF_ERR_BAD_PARAMETER);
2496	}
2497
2498	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2499	if (rv != KMF_OK) {
2500		return (rv);
2501	}
2502
2503	issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
2504	    numattr);
2505	subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
2506	    numattr);
2507
2508	/* Caller must specify issuer or subject but not both */
2509	if ((issuername == NULL && subjectname == NULL) ||
2510	    (issuername != NULL && subjectname != NULL))
2511		return (KMF_ERR_BAD_PARAMETER);
2512
2513	/* Find the CRL based on the deletion criteria. */
2514	if (issuername != NULL) {
2515		/*
2516		 * If the deletion is based on the issuer's certificate
2517		 * nickname, we will get the issuer's cert first, then
2518		 * get the CRL from the cert.
2519		 */
2520		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2521		    issuername);
2522		if (!cert) {
2523			SET_ERROR(kmfh, PORT_GetError());
2524			rv = KMF_ERR_CERT_NOT_FOUND;
2525			goto out;
2526		}
2527
2528		crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
2529		    SEC_CRL_TYPE);
2530		if (crl == NULL) {
2531			SET_ERROR(kmfh, PORT_GetError());
2532			rv = KMF_ERR_CRL_NOT_FOUND;
2533			goto out;
2534		}
2535	} else {
2536		/*
2537		 * If the deletion is based on the CRL's subject name, we will
2538		 * get all the CRLs from the internal database and search
2539		 * for the CRL with the same subject name.
2540		 */
2541		boolean_t found = B_FALSE;
2542		int nssrv;
2543
2544		nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2545		if (nssrv) {
2546			SET_ERROR(kmfh, nssrv);
2547			rv = KMF_ERR_CRL_NOT_FOUND;
2548			goto out;
2549		}
2550
2551		if (crlList == NULL) {
2552			SET_ERROR(kmfh, PORT_GetError());
2553			rv = KMF_ERR_CRL_NOT_FOUND;
2554			goto out;
2555		}
2556
2557		/* Allocate space for name */
2558		arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2559		if (arena == NULL) {
2560			rv = KMF_ERR_MEMORY;
2561			goto out;
2562		}
2563
2564		name = PORT_ArenaZAlloc(arena, sizeof (*name));
2565		if (name == NULL) {
2566			rv = KMF_ERR_MEMORY;
2567			goto out;
2568		}
2569		name->arena = arena;
2570
2571		crlNode  = crlList->first;
2572		while (crlNode && !found) {
2573			char *asciiname = NULL;
2574			SECItem* issuer;
2575
2576			name = &crlNode->crl->crl.name;
2577			if (!name) {
2578				SET_ERROR(kmfh, PORT_GetError());
2579				rv = KMF_ERR_CRL_NOT_FOUND;
2580				break;
2581			}
2582
2583			asciiname = CERT_NameToAscii(name);
2584			if (asciiname == NULL) {
2585				SET_ERROR(kmfh, PORT_GetError());
2586				rv = KMF_ERR_CRL_NOT_FOUND;
2587				break;
2588			}
2589
2590			if (strcmp(subjectname, asciiname) == 0) {
2591				found = B_TRUE;
2592				issuer = &crlNode->crl->crl.derName;
2593				crl = SEC_FindCrlByName(certHandle, issuer,
2594				    SEC_CRL_TYPE);
2595				if (crl == NULL) {
2596					/* We found a cert but no CRL */
2597					SET_ERROR(kmfh,  PORT_GetError());
2598					rv = KMF_ERR_CRL_NOT_FOUND;
2599				}
2600			}
2601			PORT_Free(asciiname);
2602			crlNode = crlNode->next;
2603		}
2604
2605		if (rv) {
2606			goto out;
2607		}
2608	}
2609
2610	if (crl) {
2611		(void) SEC_DeletePermCRL(crl);
2612	}
2613
2614out:
2615	if (nss_slot != NULL) {
2616		PK11_FreeSlot(nss_slot);
2617	}
2618
2619	if (crlList != NULL) {
2620		PORT_FreeArena(crlList->arena, PR_FALSE);
2621	}
2622
2623	if (arena != NULL) {
2624		PORT_FreeArena(arena, PR_FALSE);
2625	}
2626
2627	if (cert != NULL) {
2628		CERT_DestroyCertificate(cert);
2629	}
2630
2631	if (crl != NULL) {
2632		SEC_DestroyCrl(crl);
2633	}
2634
2635	return (rv);
2636}
2637
2638KMF_RETURN
2639NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2640{
2641	KMF_RETURN rv = KMF_OK;
2642	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2643	PK11SlotInfo *nss_slot = NULL;
2644	CERTCrlHeadNode *crlList = NULL;
2645	CERTCrlNode *crlNode = NULL;
2646	PRArenaPool *arena = NULL;
2647	CERTName *name = NULL;
2648	SECStatus nssrv;
2649	char *asciiname = NULL;
2650	int crl_num;
2651	int i, *CRLCount;
2652	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2653	char **CRLNameList;
2654
2655	if (numattr == 0 || attrlist == NULL) {
2656		return (KMF_ERR_BAD_PARAMETER);
2657	}
2658
2659	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2660	if (rv != KMF_OK) {
2661		return (rv);
2662	}
2663
2664	CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR,	attrlist, numattr);
2665	if (CRLCount == NULL)
2666		return (KMF_ERR_BAD_PARAMETER);
2667
2668	CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
2669	    attrlist, numattr);
2670
2671	/* Look up Crls */
2672	nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2673	if (nssrv) {
2674		SET_ERROR(kmfh, rv);
2675		rv = KMF_ERR_CRL_NOT_FOUND;
2676		goto out;
2677	}
2678
2679	/* Allocate space for name first */
2680	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2681	if (arena == NULL) {
2682		rv = KMF_ERR_MEMORY;
2683		goto out;
2684	}
2685
2686	name = PORT_ArenaZAlloc(arena, sizeof (*name));
2687	if (name == NULL) {
2688		rv = KMF_ERR_MEMORY;
2689		goto out;
2690	}
2691	name->arena = arena;
2692
2693	/*
2694	 * Loop thru the crlList and create a crl list with CRL's subject name.
2695	 */
2696	crlNode  = crlList->first;
2697	crl_num = 0;
2698	while (crlNode) {
2699		char *subj_name;
2700
2701		/* Get the CRL subject name */
2702		name = &crlNode->crl->crl.name;
2703		if (!name) {
2704			SET_ERROR(kmfh, PORT_GetError());
2705			rv = KMF_ERR_CRL_NOT_FOUND;
2706			break;
2707		}
2708
2709
2710		if (CRLNameList != NULL) {
2711			asciiname = CERT_NameToAscii(name);
2712			if (asciiname == NULL) {
2713				SET_ERROR(kmfh, PORT_GetError());
2714				rv = KMF_ERR_CRL_NOT_FOUND;
2715				break;
2716			}
2717			subj_name = strdup(asciiname);
2718			PORT_Free(asciiname);
2719			if (subj_name == NULL) {
2720				rv = KMF_ERR_MEMORY;
2721				break;
2722			}
2723			CRLNameList[crl_num] = subj_name;
2724		}
2725
2726		crl_num++;
2727		crlNode = crlNode->next;
2728	}
2729
2730	if (rv == KMF_OK) {
2731		/* success */
2732		*CRLCount = crl_num;
2733	}
2734
2735out:
2736	if (nss_slot != NULL) {
2737		PK11_FreeSlot(nss_slot);
2738	}
2739
2740	if (crlList != NULL) {
2741		PORT_FreeArena(crlList->arena, PR_FALSE);
2742	}
2743
2744	if (arena != NULL) {
2745		PORT_FreeArena(arena, PR_FALSE);
2746	}
2747
2748	/* If failed, free memory allocated for the returning rlist */
2749	if (rv && (CRLNameList != NULL)) {
2750		for (i = 0; i < crl_num; i++) {
2751			free(CRLNameList[i]);
2752		}
2753	}
2754
2755	return (rv);
2756}
2757
2758KMF_RETURN
2759NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2760{
2761	KMF_RETURN rv = KMF_OK;
2762	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2763	PK11SlotInfo *nss_slot = NULL;
2764	CERTCertificate *cert = NULL;
2765	CERTSignedCrl *crl = NULL;
2766	CERTCrlEntry *entry;
2767	boolean_t match = B_FALSE;
2768	int i;
2769	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2770	char *certlabel;
2771	KMF_DATA *certdata;
2772
2773	/* check params */
2774	if (numattr == 0 || attrlist == NULL) {
2775		return (KMF_ERR_BAD_PARAMETER);
2776	}
2777
2778	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2779	if (rv != KMF_OK) {
2780		return (rv);
2781	}
2782
2783	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2784
2785	/* Find the certificate first */
2786	if (certlabel != NULL) {
2787		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2788		    certlabel);
2789	} else {
2790		SECItem derCert = { NULL, 0};
2791
2792		certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
2793		    attrlist, numattr);
2794
2795		if (certdata == NULL)
2796			return (KMF_ERR_BAD_PARAMETER);
2797
2798		derCert.data = certdata->Data;
2799		derCert.len = certdata->Length;
2800
2801		cert = CERT_FindCertByDERCert(certHandle, &derCert);
2802	}
2803
2804	if (cert == NULL) {
2805		SET_ERROR(kmfh, PORT_GetError());
2806		rv = KMF_ERR_CERT_NOT_FOUND;
2807		goto out;
2808	}
2809
2810	/* Find the CRL with the same issuer as the given certificate. */
2811	crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
2812	if (crl == NULL) {
2813		/*
2814		 * Could not find the CRL issued by the same issuer. This
2815		 * usually means that the CRL is not installed in the DB.
2816		 */
2817		SET_ERROR(kmfh, PORT_GetError());
2818		rv = KMF_ERR_CRL_NOT_FOUND;
2819		goto out;
2820
2821	}
2822
2823	/* Check if the certificate's serialNumber is revoked in the CRL */
2824	i = 0;
2825	while ((entry = (crl->crl).entries[i++]) != NULL) {
2826		if (SECITEM_CompareItem(&(cert->serialNumber),
2827		    &(entry->serialNumber)) == SECEqual) {
2828			match = B_TRUE;
2829			break;
2830		}
2831	}
2832
2833	if (!match) {
2834		rv = KMF_ERR_NOT_REVOKED;
2835	}
2836
2837out:
2838	if (nss_slot != NULL) {
2839		PK11_FreeSlot(nss_slot);
2840	}
2841
2842	if (cert != NULL) {
2843		CERT_DestroyCertificate(cert);
2844	}
2845
2846	if (crl != NULL) {
2847		SEC_DestroyCrl(crl);
2848	}
2849
2850	return (rv);
2851}
2852