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