nss_spi.c revision 4025:d8be2f0444ab
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	uint32_t maxcerts = *numcerts;
561
562	*numcerts = 0;
563
564	for (node = CERT_LIST_HEAD(nsscerts);
565		!CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
566		(*numcerts) < maxcerts;
567		node = CERT_LIST_NEXT(node), (*numcerts)++) {
568		if (kmfcerts != NULL)
569			rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
570	}
571
572	/*
573	 * If we failed, delete any certs allocated so far.
574	 */
575	if (rv != KMF_OK) {
576		int i;
577		for (i = 0; i < *numcerts; i++)
578			KMF_FreeKMFCert(kmfhandle, &kmfcerts[i]);
579		*numcerts = 0;
580	}
581	return (rv);
582}
583
584KMF_RETURN
585NSS_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *params,
586	KMF_X509_DER_CERT *kmfcerts,
587	uint32_t *num_certs)
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
595	rv = Do_NSS_Init(handle,
596		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
597	if (rv != KMF_OK) {
598		return (rv);
599	}
600
601	if (*num_certs == 0)
602		maxcerts = 0xFFFFFFFF;
603	else
604		maxcerts = *num_certs;
605
606	*num_certs = 0;
607	if (params->certLabel) {
608		/* This will only find 1 certificate */
609		rv = nss_getcert_by_label(kmfh,
610			params->certLabel,
611			kmfcerts, num_certs, params->find_cert_validity);
612	} else {
613		/*
614		 * Build a list of matching certs.
615		 */
616		rv = nss_find_matching_certs(nss_slot,
617			params->issuer, params->subject, params->serial,
618			&certlist, params->find_cert_validity);
619
620		/*
621		 * If the caller supplied a pointer to storage for
622		 * a list of certs, convert up to 'maxcerts' of the
623		 * matching certs.
624		 */
625		if (rv == KMF_OK && certlist != NULL) {
626			rv = convertCertList(handle,
627				certlist, kmfcerts, &maxcerts);
628			CERT_DestroyCertList(certlist);
629			if (rv == KMF_OK)
630				*num_certs = maxcerts;
631		}
632	}
633
634	if (nss_slot != NULL) {
635		PK11_FreeSlot(nss_slot);
636	}
637
638	if (rv == KMF_OK && *num_certs == 0)
639		rv = KMF_ERR_CERT_NOT_FOUND;
640
641	return (rv);
642}
643
644void
645/*ARGSUSED*/
646NSS_FreeKMFCert(KMF_HANDLE_T handle,
647	KMF_X509_DER_CERT *kmf_cert)
648{
649	if (kmf_cert != NULL) {
650		if (kmf_cert->certificate.Data != NULL) {
651			free(kmf_cert->certificate.Data);
652			kmf_cert->certificate.Data = NULL;
653			kmf_cert->certificate.Length = 0;
654		}
655		if (kmf_cert->kmf_private.label != NULL) {
656			free(kmf_cert->kmf_private.label);
657			kmf_cert->kmf_private.label = NULL;
658		}
659	}
660}
661
662KMF_RETURN
663NSS_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
664	KMF_DATA *pcert)
665{
666	KMF_RETURN ret = KMF_OK;
667	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
668	SECStatus nss_rv;
669	CERTCertificate *nss_cert = NULL;
670	CERTCertTrust *nss_trust = NULL;
671	PK11SlotInfo *nss_slot = NULL;
672	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
673
674	if (pcert == NULL) {
675		return (KMF_ERR_BAD_PARAMETER);
676	}
677
678	/* NSS only support DER format */
679	if (params == NULL) {
680		return (KMF_ERR_BAD_PARAMETER);
681	}
682
683	ret = Do_NSS_Init(handle,
684		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
685	if (ret != KMF_OK) {
686		return (ret);
687	}
688
689	nss_cert = CERT_DecodeCertFromPackage((char *)pcert->Data,
690	    pcert->Length);
691	if (nss_cert == NULL) {
692		SET_ERROR(kmfh, PORT_GetError());
693		ret = KMF_ERR_BAD_CERT_FORMAT;
694		goto out;
695	}
696
697	nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
698	    params->certLabel, 0);
699	if (nss_rv) {
700		SET_ERROR(kmfh, nss_rv);
701		ret = KMF_ERR_BAD_CERT_FORMAT;
702		goto out;
703	}
704
705	if (params->ks_opt_u.nss_opts.trustflag != NULL &&
706		strlen(params->ks_opt_u.nss_opts.trustflag)) {
707		nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
708		if (nss_trust == NULL) {
709			ret = KMF_ERR_MEMORY;
710				goto out;
711		}
712		nss_rv = CERT_DecodeTrustString(nss_trust,
713			params->ks_opt_u.nss_opts.trustflag);
714		if (nss_rv) {
715			SET_ERROR(kmfh, nss_rv);
716			ret = KMF_ERR_BAD_PARAMETER;
717			goto out;
718		}
719
720		nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
721		if (nss_rv) {
722			SET_ERROR(kmfh, nss_rv);
723			ret = KMF_ERR_BAD_PARAMETER;
724		}
725	}
726
727out:
728	if (nss_trust != NULL) {
729		free(nss_trust);
730	}
731
732	if (nss_cert != NULL) {
733		CERT_DestroyCertificate(nss_cert);
734	}
735
736	if (nss_slot != NULL) {
737		PK11_FreeSlot(nss_slot);
738	}
739
740	return (ret);
741}
742
743
744KMF_RETURN
745NSS_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *params)
746{
747	KMF_RETURN ret = KMF_OK;
748	KMF_STORECERT_PARAMS scparams;
749	KMF_DATA cert = {NULL, 0};
750	KMF_DATA cert_der = {NULL, 0};
751	KMF_DATA *cptr = NULL;
752	KMF_ENCODE_FORMAT format;
753
754	if (params == NULL || params->certfile == NULL) {
755		return (KMF_ERR_BAD_PARAMETER);
756	}
757
758	/*
759	 * Check if the input cert file is a valid certificate and
760	 * auto-detect the file format of it.
761	 */
762	ret = KMF_IsCertFile(handle, params->certfile, &format);
763	if (ret != KMF_OK)
764		return (ret);
765
766	ret = KMF_ReadInputFile(handle, params->certfile, &cert);
767	if (ret != KMF_OK) {
768		return (ret);
769	}
770
771	/*
772	 * If the imported cert is in PEM format, convert it to
773	 * DER format in order to store it in NSS token.
774	 */
775	if (format == KMF_FORMAT_PEM) {
776		int derlen;
777		ret = KMF_Pem2Der(cert.Data, cert.Length,
778		    &cert_der.Data, &derlen);
779		if (ret != KMF_OK) {
780			goto cleanup;
781		}
782		cert_der.Length = (size_t)derlen;
783		cptr = &cert_der;
784	} else {
785		cptr = &cert;
786	}
787
788	(void) memset(&scparams, 0, sizeof (scparams));
789	scparams.kstype = params->kstype;
790	scparams.certLabel = params->certLabel;
791	scparams.nssparms = params->nssparms;
792
793	ret = NSS_StoreCert(handle, &scparams, cptr);
794
795	if (format == KMF_FORMAT_PEM) {
796		KMF_FreeData(&cert_der);
797	}
798
799cleanup:
800	KMF_FreeData(&cert);
801
802	return (ret);
803}
804
805KMF_RETURN
806NSS_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
807{
808	KMF_RETURN rv = KMF_OK;
809	int nssrv;
810	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
811	CERTCertificate *cert = NULL;
812	PK11SlotInfo *nss_slot = NULL;
813
814	/* check params */
815	if (params == NULL) {
816		return (KMF_ERR_BAD_PARAMETER);
817	}
818
819	rv = Do_NSS_Init(handle,
820		params->ks_opt_u.nss_opts,
821		FALSE, &nss_slot);
822	if (rv != KMF_OK) {
823		return (rv);
824	}
825
826	if (params->certLabel) {
827		cert = PK11_FindCertFromNickname(params->certLabel, NULL);
828		if (cert == NULL) {
829			return (KMF_ERR_CERT_NOT_FOUND);
830		}
831
832		switch (params->find_cert_validity) {
833		case KMF_ALL_CERTS:
834			break;
835		case KMF_NONEXPIRED_CERTS:
836			nssrv = CERT_CertTimesValid(cert);
837			if (nssrv == SECFailure) {
838				/* this is an invalid cert - skip it */
839				goto out;
840			}
841			break;
842		case KMF_EXPIRED_CERTS:
843			nssrv = CERT_CertTimesValid(cert);
844			if (nssrv != SECFailure) {
845				/* this is a valid cert - skip it */
846				goto out;
847			}
848			break;
849		}
850		/* delete it from database */
851		nssrv = SEC_DeletePermCertificate(cert);
852		if (nssrv) {
853			SET_ERROR(kmfh, nssrv);
854			rv = KMF_ERR_INTERNAL;
855		}
856	} else {
857		CERTCertListNode *node;
858		CERTCertList *certlist = NULL;
859
860		rv = nss_find_matching_certs(nss_slot,
861			params->issuer, params->subject, params->serial,
862			&certlist, params->find_cert_validity);
863
864		for (node = CERT_LIST_HEAD(certlist);
865			!CERT_LIST_END(node, certlist) && rv == KMF_OK;
866			node = CERT_LIST_NEXT(node)) {
867
868			nssrv = SEC_DeletePermCertificate(node->cert);
869			if (nssrv) {
870				SET_ERROR(kmfh, nssrv);
871				rv = KMF_ERR_INTERNAL;
872			}
873		}
874
875		if (rv == KMF_OK && certlist != NULL) {
876			CERT_DestroyCertList(certlist);
877		} else if (rv == KMF_OK && certlist == NULL) {
878			rv = KMF_ERR_CERT_NOT_FOUND;
879		}
880	}
881out:
882	if (nss_slot != NULL) {
883		PK11_FreeSlot(nss_slot);
884	}
885
886	if (cert != NULL) {
887		CERT_DestroyCertificate(cert);
888	}
889
890	return (rv);
891}
892
893static void
894InitRandom(char *filename)
895{
896	char buf[2048];
897	int fd;
898	PRInt32 count;
899
900	fd = open(filename, O_RDONLY);
901	if (!fd)
902		return;
903
904	count = read(fd, buf, sizeof (buf));
905	if (count > 0) {
906		PK11_RandomUpdate(buf, count);
907	}
908
909	(void) close(fd);
910}
911
912KMF_RETURN
913NSS_CreateKeypair(KMF_HANDLE_T handle,
914	KMF_CREATEKEYPAIR_PARAMS *params,
915	KMF_KEY_HANDLE *privkey,
916	KMF_KEY_HANDLE *pubkey)
917{
918	KMF_RETURN rv = KMF_OK;
919	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
920	PK11RSAGenParams	rsaparams;
921	void	*nssparams;
922	CK_MECHANISM_TYPE mechanism;
923	ulong_t publicExponent = 0x010001;
924	PK11SlotInfo *nss_slot = NULL;
925	SECKEYPrivateKey *NSSprivkey = NULL;
926	SECKEYPublicKey *NSSpubkey = NULL;
927	PQGParams *pqgParams = NULL;
928
929
930	if (params == NULL) {
931		return (KMF_ERR_BAD_PARAMETER);
932	}
933
934	rv = Do_NSS_Init(handle,
935		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
936	if (rv != KMF_OK) {
937		return (rv);
938	}
939
940	rv = nss_authenticate(handle, nss_slot, &params->cred);
941	if (rv != KMF_OK) {
942		return (rv);
943	}
944
945	/* Get some random bits */
946	InitRandom("/dev/urandom");
947	if (params->keytype == KMF_RSA) {
948		rsaparams.keySizeInBits = params->keylength;
949		/*
950		 * NSS only allows for a 4 byte exponent.
951		 * Ignore the exponent parameter if it is too big.
952		 */
953		if (params->rsa_exponent.len > 0 &&
954		    params->rsa_exponent.len <= sizeof (publicExponent) &&
955		    params->rsa_exponent.val != NULL) {
956			(void) memcpy(&publicExponent,
957				params->rsa_exponent.val,
958				params->rsa_exponent.len);
959		}
960		rsaparams.pe = publicExponent;
961		mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
962		nssparams = &rsaparams;
963	} else if (params->keytype == KMF_DSA) {
964		PQGVerify *pqgVerify = NULL;
965		int ks;
966		SECStatus	nssrv, passed;
967
968		mechanism = CKM_DSA_KEY_PAIR_GEN;
969
970		ks = PQG_PBITS_TO_INDEX(params->keylength);
971		nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
972		if (nssrv != SECSuccess) {
973			SET_ERROR(kmfh, rv);
974			PK11_PQG_DestroyVerify(pqgVerify);
975			rv = KMF_ERR_KEYGEN_FAILED;
976			goto cleanup;
977		}
978
979		nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
980		if (nssrv != SECSuccess || passed != SECSuccess) {
981			SET_ERROR(kmfh, rv);
982			rv = KMF_ERR_KEYGEN_FAILED;
983		}
984
985		PK11_PQG_DestroyVerify(pqgVerify);
986
987		if (rv != KMF_OK) {
988			SET_ERROR(kmfh, PORT_GetError());
989			goto cleanup;
990		}
991
992		nssparams = pqgParams;
993	} else {
994		rv = KMF_ERR_BAD_PARAMETER;
995		goto cleanup;
996	}
997
998	NSSprivkey = PK11_GenerateKeyPair(nss_slot,
999		mechanism, nssparams, &NSSpubkey,
1000		PR_TRUE, /* isPermanent */
1001		PR_TRUE, /* isSensitive */
1002		(void *)params->cred.cred);
1003
1004	if (NSSprivkey == NULL || NSSpubkey == NULL) {
1005		SET_ERROR(kmfh, PORT_GetError());
1006		rv = KMF_ERR_KEYGEN_FAILED;
1007	} else {
1008		if (params->keylabel != NULL &&
1009			strlen(params->keylabel)) {
1010			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
1011				params->keylabel);
1012			(void) PK11_SetPublicKeyNickname(NSSpubkey,
1013				params->keylabel);
1014		}
1015		/* Now, convert it to a KMF_KEY object for the framework */
1016		if (privkey != NULL) {
1017			privkey->kstype = KMF_KEYSTORE_NSS;
1018			privkey->keyalg = params->keytype;
1019			privkey->keyclass = KMF_ASYM_PRI;
1020			privkey->keylabel =
1021				PK11_GetPrivateKeyNickname(NSSprivkey);
1022			privkey->keyp = (void *)NSSprivkey;
1023		}
1024		if (pubkey != NULL) {
1025			pubkey->kstype = KMF_KEYSTORE_NSS;
1026			pubkey->keyalg = params->keytype;
1027			pubkey->keyp = (void *)NSSpubkey;
1028			pubkey->keyclass = KMF_ASYM_PUB;
1029			pubkey->keylabel =
1030				PK11_GetPublicKeyNickname(NSSpubkey);
1031		}
1032		rv = KMF_OK;
1033	}
1034cleanup:
1035	if (rv != KMF_OK) {
1036		if (NSSpubkey)
1037			PK11_DeleteTokenPublicKey(NSSpubkey);
1038		if (NSSprivkey)
1039			PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
1040
1041		privkey->keyp = NULL;
1042		pubkey->keyp = NULL;
1043	}
1044
1045	if (pqgParams != NULL)
1046		PK11_PQG_DestroyParams(pqgParams);
1047
1048
1049	if (nss_slot != NULL)
1050		PK11_FreeSlot(nss_slot);
1051
1052	return (rv);
1053}
1054
1055KMF_RETURN
1056NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1057	KMF_OID *AlgOID, KMF_DATA *tobesigned,
1058	KMF_DATA *output)
1059{
1060	KMF_RETURN		ret = KMF_OK;
1061	KMF_ALGORITHM_INDEX		AlgId;
1062	SECOidTag		signAlgTag;
1063	SECKEYPrivateKey	*NSSprivkey = NULL;
1064	SECStatus		rv;
1065	SECItem			signed_data;
1066	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1067
1068	signed_data.data = 0;
1069	if (key == NULL || AlgOID == NULL ||
1070	    tobesigned == NULL || output == NULL ||
1071	    tobesigned->Data == NULL ||
1072	    output->Data == NULL)
1073		return (KMF_ERR_BAD_PARAMETER);
1074
1075	/* Map the OID to a NSS algorithm */
1076	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
1077	if (AlgId == KMF_ALGID_NONE)
1078		return (KMF_ERR_BAD_PARAMETER);
1079
1080	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1081
1082	if (AlgId == KMF_ALGID_MD5WithRSA)
1083		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1084	else if (AlgId == KMF_ALGID_MD2WithRSA)
1085		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1086	else if (AlgId == KMF_ALGID_SHA1WithRSA)
1087		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1088	else if (AlgId == KMF_ALGID_SHA1WithDSA)
1089		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1090	else
1091		return (KMF_ERR_BAD_PARAMETER);
1092
1093	rv = SEC_SignData(&signed_data, tobesigned->Data,
1094	    tobesigned->Length, NSSprivkey, signAlgTag);
1095
1096	if (rv != 0) {
1097		SET_ERROR(kmfh, rv);
1098		return (KMF_ERR_INTERNAL);
1099	}
1100
1101	if (signed_data.len <= output->Length) {
1102		(void) memcpy(output->Data, signed_data.data, signed_data.len);
1103		output->Length = signed_data.len;
1104	} else {
1105		output->Length = 0;
1106		ret = KMF_ERR_BAD_PARAMETER;
1107	}
1108	free(signed_data.data);
1109
1110	return (ret);
1111}
1112
1113KMF_RETURN
1114NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1115	KMF_DATA *encoded)
1116{
1117	KMF_RETURN ret = KMF_OK;
1118	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1119	SECItem *rvitem;
1120	CERTSubjectPublicKeyInfo *spki = NULL;
1121
1122	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1123		return (KMF_ERR_BAD_PARAMETER);
1124
1125	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1126	if (spki == NULL) {
1127		SET_ERROR(kmfh, PORT_GetError());
1128		return (KMF_ERR_MEMORY);
1129	}
1130
1131	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1132		CERT_SubjectPublicKeyInfoTemplate);
1133
1134	if (rvitem != NULL) {
1135		encoded->Data = malloc(rvitem->len);
1136		if (encoded->Data == NULL) {
1137			ret = KMF_ERR_MEMORY;
1138		} else {
1139			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1140			encoded->Length = rvitem->len;
1141		}
1142		SECITEM_FreeItem(rvitem, TRUE);
1143	} else {
1144		SET_ERROR(kmfh, PORT_GetError());
1145		encoded->Data = NULL;
1146		encoded->Length = 0;
1147		ret = KMF_ERR_ENCODING;
1148	}
1149	SECKEY_DestroySubjectPublicKeyInfo(spki);
1150
1151	return (ret);
1152}
1153
1154KMF_RETURN
1155NSS_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1156	KMF_KEY_HANDLE *key, boolean_t delete_token)
1157{
1158	KMF_RETURN rv = KMF_OK;
1159	PK11SlotInfo *nss_slot = NULL;
1160
1161	/*
1162	 * "delete_token" means to clear it from the token storage as well
1163	 * as from memory.
1164	 */
1165	if (key == NULL || key->keyp == NULL)
1166		return (KMF_ERR_BAD_PARAMETER);
1167
1168	if (delete_token) {
1169		SECStatus nssrv = SECSuccess;
1170		if (key->keyclass != KMF_ASYM_PUB &&
1171			key->keyclass != KMF_ASYM_PRI &&
1172			key->keyclass != KMF_SYMMETRIC)
1173			return (KMF_ERR_BAD_KEY_CLASS);
1174
1175		if (params == NULL)
1176			return (KMF_ERR_BAD_PARAMETER);
1177		rv = Do_NSS_Init(handle,
1178			params->ks_opt_u.nss_opts, FALSE, &nss_slot);
1179		if (rv != KMF_OK) {
1180			return (rv);
1181		}
1182		rv = nss_authenticate(handle, nss_slot, &params->cred);
1183		if (rv != KMF_OK) {
1184			return (rv);
1185		}
1186
1187		if (key->keyclass == KMF_ASYM_PUB) {
1188			nssrv = PK11_DeleteTokenPublicKey(
1189				(SECKEYPublicKey *)key->keyp);
1190		} else if (key->keyclass == KMF_ASYM_PRI) {
1191			nssrv = PK11_DeleteTokenPrivateKey(
1192				(SECKEYPrivateKey *)key->keyp, PR_TRUE);
1193		} else if (key->keyclass == KMF_SYMMETRIC) {
1194			nssrv = PK11_DeleteTokenSymKey(
1195					(PK11SymKey *) key->keyp);
1196			if (nssrv == SECSuccess)
1197				PK11_FreeSymKey(
1198					(PK11SymKey *) key->keyp);
1199		}
1200		if (nssrv != SECSuccess) {
1201			SET_ERROR(handle, PORT_GetError());
1202			rv = KMF_ERR_INTERNAL;
1203		}
1204	} else {
1205		if (key->keyclass == KMF_ASYM_PUB) {
1206			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1207		} else if (key->keyclass == KMF_ASYM_PRI) {
1208			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1209		} else if (key->keyclass == KMF_SYMMETRIC) {
1210			PK11_FreeSymKey((PK11SymKey *) key->keyp);
1211		} else {
1212			return (KMF_ERR_BAD_KEY_CLASS);
1213		}
1214	}
1215	key->keyp = NULL;
1216
1217	return (rv);
1218}
1219
1220KMF_RETURN
1221NSS_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
1222{
1223	KMF_RETURN ret = KMF_OK;
1224	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1225	PK11SlotInfo *nss_slot = NULL;
1226	CERTSignedCrl *nss_crl = NULL;
1227	KMF_ENCODE_FORMAT format;
1228	int importOptions;
1229	SECItem crlDER;
1230	KMF_DATA crl1;
1231	KMF_DATA crl2;
1232
1233	if (params == NULL || params->ks_opt_u.nss_opts.crlfile == NULL) {
1234		return (KMF_ERR_BAD_PARAMETER);
1235	}
1236
1237	/*
1238	 * Check if the input CRL file is a valid CRL file and auto-detect
1239	 * the encoded format of the file.
1240	 */
1241	ret = KMF_IsCRLFile(handle, params->ks_opt_u.nss_opts.crlfile,
1242	    &format);
1243	if (ret != KMF_OK)
1244		return (ret);
1245
1246	ret = Do_NSS_Init(handle,
1247		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1248	if (ret != KMF_OK) {
1249		return (ret);
1250	}
1251
1252	/* set importOptions */
1253	if (params->ks_opt_u.nss_opts.crl_check == B_FALSE) {
1254		importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
1255		    CRL_IMPORT_BYPASS_CHECKS;
1256	} else {
1257		importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
1258	}
1259
1260
1261	/* Read in the CRL file */
1262	crl1.Data = NULL;
1263	crl2.Data = NULL;
1264	ret = KMF_ReadInputFile(handle, params->ks_opt_u.nss_opts.crlfile,
1265	    &crl1);
1266	if (ret != KMF_OK) {
1267		return (ret);
1268	}
1269
1270	/* If the input CRL is in PEM format, convert it to DER first. */
1271	if (format == KMF_FORMAT_PEM) {
1272		int len;
1273		ret = KMF_Pem2Der(crl1.Data, crl1.Length,
1274		    &crl2.Data, &len);
1275		if (ret != KMF_OK) {
1276			goto out;
1277		}
1278		crl2.Length = (size_t)len;
1279	}
1280
1281	crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
1282	crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
1283
1284	nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
1285	    NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
1286
1287	if (nss_crl == NULL) {
1288		SET_ERROR(kmfh, PORT_GetError());
1289		ret = KMF_ERR_BAD_CRLFILE;
1290		goto out;
1291	}
1292
1293out:
1294	if (nss_slot != NULL) {
1295		PK11_FreeSlot(nss_slot);
1296	}
1297
1298	if (crl1.Data != NULL) {
1299		free(crl1.Data);
1300	}
1301
1302	if (crl2.Data != NULL) {
1303		free(crl2.Data);
1304	}
1305
1306	if (nss_crl != NULL) {
1307		SEC_DestroyCrl(nss_crl);
1308	}
1309
1310	return (ret);
1311}
1312
1313KMF_RETURN
1314NSS_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
1315{
1316	KMF_RETURN rv = KMF_OK;
1317	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1318	CERTSignedCrl *crl = NULL;
1319	CERTCertificate *cert = NULL;
1320	PK11SlotInfo *nss_slot = NULL;
1321	CERTCrlHeadNode *crlList = NULL;
1322	CERTCrlNode *crlNode = NULL;
1323	PRArenaPool *arena = NULL;
1324	CERTName *name = NULL;
1325	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1326
1327	/* check params */
1328	if (params == NULL ||
1329	    (params->ks_opt_u.nss_opts.crl_issuerName == NULL &&
1330	    params->ks_opt_u.nss_opts.crl_subjName == NULL) ||
1331	    (params->ks_opt_u.nss_opts.crl_issuerName != NULL &&
1332	    params->ks_opt_u.nss_opts.crl_subjName != NULL)) {
1333		return (KMF_ERR_BAD_PARAMETER);
1334	}
1335
1336	rv = Do_NSS_Init(handle,
1337		params->ks_opt_u.nss_opts, TRUE,
1338		&nss_slot);
1339	if (rv != KMF_OK) {
1340		return (rv);
1341	}
1342
1343	/* Find the CRL based on the deletion criteria. */
1344	if (params->ks_opt_u.nss_opts.crl_issuerName != NULL) {
1345		/*
1346		 * If the deletion is based on the issuer's certificate
1347		 * nickname, we will get the issuer's cert first, then
1348		 * get the CRL from the cert.
1349		 */
1350		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
1351		    params->ks_opt_u.nss_opts.crl_issuerName);
1352		if (!cert) {
1353			SET_ERROR(kmfh, PORT_GetError());
1354			rv = KMF_ERR_CERT_NOT_FOUND;
1355			goto out;
1356		}
1357
1358		crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
1359		    SEC_CRL_TYPE);
1360		if (crl == NULL) {
1361			SET_ERROR(kmfh, PORT_GetError());
1362			rv = KMF_ERR_CRL_NOT_FOUND;
1363			goto out;
1364		}
1365	} else {
1366		/*
1367		 * If the deletion is based on the CRL's subject name, we will
1368		 * get all the CRLs from the internal database and search
1369		 * for the CRL with the same subject name.
1370		 */
1371		boolean_t found = B_FALSE;
1372		int nssrv;
1373
1374		nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
1375		if (nssrv) {
1376			SET_ERROR(kmfh, nssrv);
1377			rv = KMF_ERR_CRL_NOT_FOUND;
1378			goto out;
1379		}
1380
1381		if (crlList == NULL) {
1382			SET_ERROR(kmfh, PORT_GetError());
1383			rv = KMF_ERR_CRL_NOT_FOUND;
1384			goto out;
1385		}
1386
1387		/* Allocate space for name */
1388		arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
1389		if (arena == NULL) {
1390			rv = KMF_ERR_MEMORY;
1391			goto out;
1392		}
1393
1394		name = PORT_ArenaZAlloc(arena, sizeof (*name));
1395		if (name == NULL) {
1396			rv = KMF_ERR_MEMORY;
1397			goto out;
1398		}
1399		name->arena = arena;
1400
1401		crlNode  = crlList->first;
1402		while (crlNode && !found) {
1403			char *asciiname = NULL;
1404			SECItem* issuer;
1405
1406			name = &crlNode->crl->crl.name;
1407			if (!name) {
1408				SET_ERROR(kmfh, PORT_GetError());
1409				rv = KMF_ERR_CRL_NOT_FOUND;
1410				break;
1411			}
1412
1413			asciiname = CERT_NameToAscii(name);
1414			if (asciiname == NULL) {
1415				SET_ERROR(kmfh, PORT_GetError());
1416				rv = KMF_ERR_CRL_NOT_FOUND;
1417				break;
1418			}
1419
1420			if (strcmp(params->ks_opt_u.nss_opts.crl_subjName,
1421			    asciiname) == 0) {
1422				found = B_TRUE;
1423				issuer = &crlNode->crl->crl.derName;
1424				crl = SEC_FindCrlByName(certHandle, issuer,
1425				    SEC_CRL_TYPE);
1426				if (crl == NULL) {
1427					/* We found a cert but no CRL */
1428					SET_ERROR(kmfh,  PORT_GetError());
1429					rv = KMF_ERR_CRL_NOT_FOUND;
1430				}
1431			}
1432			PORT_Free(asciiname);
1433			crlNode = crlNode->next;
1434		}
1435
1436		if (rv) {
1437			goto out;
1438		}
1439	}
1440
1441	if (crl) {
1442		(void) SEC_DeletePermCRL(crl);
1443	}
1444
1445out:
1446	if (nss_slot != NULL) {
1447		PK11_FreeSlot(nss_slot);
1448	}
1449
1450	if (crlList != NULL) {
1451		PORT_FreeArena(crlList->arena, PR_FALSE);
1452	}
1453
1454	if (arena != NULL) {
1455		PORT_FreeArena(arena, PR_FALSE);
1456	}
1457
1458	if (cert != NULL) {
1459		CERT_DestroyCertificate(cert);
1460	}
1461
1462	if (crl != NULL) {
1463		SEC_DestroyCrl(crl);
1464	}
1465
1466	return (rv);
1467}
1468
1469
1470KMF_RETURN
1471NSS_FindCRL(KMF_HANDLE_T handle, KMF_FINDCRL_PARAMS *params,
1472	char **CRLNameList, int *CRLCount)
1473{
1474	KMF_RETURN rv = KMF_OK;
1475	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1476	PK11SlotInfo *nss_slot = NULL;
1477	CERTCrlHeadNode *crlList = NULL;
1478	CERTCrlNode *crlNode = NULL;
1479	PRArenaPool *arena = NULL;
1480	CERTName *name = NULL;
1481	SECStatus nssrv;
1482	char *asciiname = NULL;
1483	int crl_num;
1484	int i;
1485	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1486
1487	if (CRLCount == NULL || params == NULL) {
1488		return (KMF_ERR_BAD_PARAMETER);
1489	}
1490
1491	*CRLCount = 0;
1492
1493	rv = Do_NSS_Init(handle,
1494		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1495	if (rv != KMF_OK) {
1496		return (rv);
1497	}
1498
1499	/* Look up Crls */
1500	nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
1501	if (nssrv) {
1502		SET_ERROR(kmfh, rv);
1503		rv = KMF_ERR_CRL_NOT_FOUND;
1504		goto out;
1505	}
1506
1507	/* Allocate space for name first */
1508	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
1509	if (arena == NULL) {
1510	    rv = KMF_ERR_MEMORY;
1511	    goto out;
1512	}
1513
1514	name = PORT_ArenaZAlloc(arena, sizeof (*name));
1515	if (name == NULL) {
1516		rv = KMF_ERR_MEMORY;
1517		goto out;
1518	}
1519	name->arena = arena;
1520
1521	/*
1522	 * Loop thru the crlList and create a crl list with CRL's subject name.
1523	 */
1524	crlNode  = crlList->first;
1525	crl_num = 0;
1526	while (crlNode) {
1527		char *subj_name;
1528
1529		/* Get the CRL subject name */
1530		name = &crlNode->crl->crl.name;
1531		if (!name) {
1532			SET_ERROR(kmfh, PORT_GetError());
1533			rv = KMF_ERR_CRL_NOT_FOUND;
1534			break;
1535		}
1536
1537
1538		if (CRLNameList != NULL) {
1539			asciiname = CERT_NameToAscii(name);
1540			if (asciiname == NULL) {
1541				SET_ERROR(kmfh, PORT_GetError());
1542				rv = KMF_ERR_CRL_NOT_FOUND;
1543				break;
1544			}
1545			subj_name = strdup(asciiname);
1546			PORT_Free(asciiname);
1547			if (subj_name == NULL) {
1548				rv = KMF_ERR_MEMORY;
1549				break;
1550			}
1551			CRLNameList[crl_num] = subj_name;
1552		}
1553
1554		crl_num++;
1555		crlNode = crlNode->next;
1556	}
1557
1558	if (rv == KMF_OK) {
1559		/* success */
1560		*CRLCount = crl_num;
1561	}
1562
1563out:
1564	if (nss_slot != NULL) {
1565		PK11_FreeSlot(nss_slot);
1566	}
1567
1568	if (crlList != NULL) {
1569		PORT_FreeArena(crlList->arena, PR_FALSE);
1570	}
1571
1572	if (arena != NULL) {
1573		PORT_FreeArena(arena, PR_FALSE);
1574	}
1575
1576	/* If failed, free memory allocated for the returning rlist */
1577	if (rv && (CRLNameList != NULL)) {
1578		for (i = 0; i < crl_num; i++) {
1579			free(CRLNameList[i]);
1580		}
1581	}
1582
1583	return (rv);
1584}
1585
1586
1587KMF_RETURN
1588NSS_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
1589{
1590	KMF_RETURN rv = KMF_OK;
1591	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1592	PK11SlotInfo *nss_slot = NULL;
1593	CERTCertificate *cert = NULL;
1594	CERTSignedCrl *crl = NULL;
1595	CERTCrlEntry *entry;
1596	boolean_t match = B_FALSE;
1597	int i;
1598	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1599
1600	/* check params */
1601	if (params == NULL ||
1602	    (params->ks_opt_u.nss_opts.certLabel == NULL &&
1603	    params->ks_opt_u.nss_opts.certificate == NULL)) {
1604		return (KMF_ERR_BAD_PARAMETER);
1605	}
1606
1607	rv = Do_NSS_Init(handle,
1608		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1609	if (rv != KMF_OK) {
1610		return (rv);
1611	}
1612
1613	/* Find the certificate first */
1614	if (params->ks_opt_u.nss_opts.certLabel != NULL) {
1615		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
1616		    params->ks_opt_u.nss_opts.certLabel);
1617	} else {
1618		SECItem derCert = { NULL, 0};
1619
1620		derCert.data = params->ks_opt_u.nss_opts.certificate->Data;
1621		derCert.len =  params->ks_opt_u.nss_opts.certificate->Length;
1622		cert = CERT_FindCertByDERCert(certHandle, &derCert);
1623	}
1624
1625	if (!cert) {
1626		SET_ERROR(kmfh, PORT_GetError());
1627		rv = KMF_ERR_CERT_NOT_FOUND;
1628		goto out;
1629	}
1630
1631	/* Find the CRL with the same issuer as the given certificate. */
1632	crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
1633	if (crl == NULL) {
1634		/*
1635		 * Could not find the CRL issued by the same issuer. This
1636		 * usually means that the CRL is not installed in the DB.
1637		 */
1638		SET_ERROR(kmfh, PORT_GetError());
1639		rv = KMF_ERR_CRL_NOT_FOUND;
1640		goto out;
1641
1642	}
1643
1644	/* Check if the certificate's serialNumber is revoked in the CRL */
1645	i = 0;
1646	while ((entry = (crl->crl).entries[i++]) != NULL) {
1647		if (SECITEM_CompareItem(&(cert->serialNumber),
1648		    &(entry->serialNumber)) == SECEqual) {
1649			match = B_TRUE;
1650			break;
1651		}
1652	}
1653
1654	if (!match) {
1655		rv = KMF_ERR_NOT_REVOKED;
1656	}
1657
1658out:
1659	if (nss_slot != NULL) {
1660		PK11_FreeSlot(nss_slot);
1661	}
1662
1663	if (cert != NULL) {
1664		CERT_DestroyCertificate(cert);
1665	}
1666
1667	if (crl != NULL) {
1668		SEC_DestroyCrl(crl);
1669	}
1670
1671	return (rv);
1672}
1673
1674KMF_RETURN
1675NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1676{
1677	KMF_RETURN ret = KMF_OK;
1678	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1679	char *str;
1680
1681	/* Get the error string in the default language */
1682	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1683
1684	if (str != NULL) {
1685		*msgstr = (char *)strdup(str);
1686		if ((*msgstr) == NULL)
1687			ret = KMF_ERR_MEMORY;
1688	} else {
1689		*msgstr = NULL;
1690	}
1691
1692	return (ret);
1693}
1694
1695KMF_RETURN
1696NSS_GetPrikeyByCert(KMF_HANDLE_T handle, KMF_CRYPTOWITHCERT_PARAMS *params,
1697	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
1698	KMF_KEY_ALG keytype)
1699{
1700	CERTCertificate *nss_cert = NULL;
1701	SECKEYPrivateKey* privkey = NULL;
1702	PK11SlotInfo *nss_slot = NULL;
1703	KMF_RETURN rv = KMF_OK;
1704	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1705
1706	rv = Do_NSS_Init(handle,
1707		params->nssparms, FALSE, &nss_slot);
1708	if (rv != KMF_OK) {
1709		return (rv);
1710	}
1711
1712	rv = nss_authenticate(handle, nss_slot, &params->cred);
1713	if (rv != KMF_OK) {
1714		return (rv);
1715	}
1716
1717	nss_cert = CERT_DecodeCertFromPackage((char *)SignerCertData->Data,
1718	    SignerCertData->Length);
1719
1720	if (nss_cert == NULL) {
1721		SET_ERROR(kmfh, PORT_GetError());
1722		return (KMF_ERR_BAD_CERT_FORMAT);
1723	}
1724
1725	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1726	if (privkey == NULL) {
1727		SET_ERROR(kmfh, PORT_GetError());
1728		return (KMF_ERR_KEY_NOT_FOUND);
1729	}
1730
1731	key->kstype = KMF_KEYSTORE_NSS;
1732	key->keyclass = KMF_ASYM_PRI;
1733	key->keyalg = keytype;
1734	key->keyp = (void *)privkey;
1735	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1736
1737	CERT_DestroyCertificate(nss_cert);
1738
1739	return (KMF_OK);
1740
1741}
1742
1743KMF_RETURN
1744NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1745	KMF_OID *AlgOID, KMF_DATA *ciphertext,
1746	KMF_DATA *output)
1747{
1748	KMF_RETURN		ret = KMF_OK;
1749	SECKEYPrivateKey	*NSSprivkey = NULL;
1750	SECStatus		rv;
1751	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1752	unsigned int in_len = 0, out_len = 0;
1753	unsigned int total_decrypted = 0, modulus_len = 0;
1754	uint8_t *in_data, *out_data;
1755	int i, blocks;
1756
1757
1758	if (key == NULL || AlgOID == NULL ||
1759	    ciphertext == NULL || output == NULL ||
1760	    ciphertext->Data == NULL ||
1761	    output->Data == NULL)
1762		return (KMF_ERR_BAD_PARAMETER);
1763
1764	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1765	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1766
1767	blocks = ciphertext->Length/modulus_len;
1768	out_data = output->Data;
1769	in_data = ciphertext->Data;
1770	out_len = modulus_len - 11;
1771	in_len = modulus_len;
1772
1773	for (i = 0; i < blocks; i++) {
1774		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1775		    &out_len, ciphertext->Length, in_data, in_len);
1776
1777		if (rv != 0) {
1778			SET_ERROR(kmfh, rv);
1779			return (KMF_ERR_INTERNAL);
1780		}
1781
1782		out_data += out_len;
1783		total_decrypted += out_len;
1784		in_data += in_len;
1785	}
1786
1787	output->Length = total_decrypted;
1788
1789	return (ret);
1790}
1791
1792static KMF_KEY_ALG
1793pk11keytype2kmf(CK_KEY_TYPE type)
1794{
1795	switch (type) {
1796	case CKK_RSA:
1797		return (KMF_RSA);
1798	case CKK_DSA:
1799		return (KMF_RSA);
1800	case CKK_AES:
1801		return (KMF_AES);
1802	case CKK_RC4:
1803		return (KMF_RC4);
1804	case CKK_DES:
1805		return (KMF_DES);
1806	case CKK_DES3:
1807		return (KMF_DES3);
1808	default:
1809		/* not supported */
1810		return (KMF_KEYALG_NONE);
1811	}
1812}
1813
1814KMF_RETURN
1815NSS_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
1816	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
1817{
1818	KMF_RETURN rv;
1819	SECKEYPrivateKeyList *prilist;
1820	SECKEYPrivateKeyListNode *prinode;
1821	SECKEYPublicKeyList *publist;
1822	SECKEYPublicKeyListNode *pubnode;
1823	PK11SlotInfo *nss_slot = NULL;
1824	PK11SymKey *symlist = NULL;
1825	int count;
1826	uint32_t maxkeys;
1827
1828	rv = Do_NSS_Init(handle,
1829		parms->ks_opt_u.nss_opts, FALSE, &nss_slot);
1830	if (rv != KMF_OK) {
1831		return (rv);
1832	}
1833
1834	rv = nss_authenticate(handle, nss_slot, &parms->cred);
1835	if (rv != KMF_OK) {
1836		return (rv);
1837	}
1838
1839	maxkeys = *numkeys;
1840	if (maxkeys == 0)
1841		maxkeys = 0xFFFFFFFF;
1842
1843	*numkeys = 0;
1844	if (parms->keyclass == KMF_ASYM_PUB) {
1845		publist = PK11_ListPublicKeysInSlot(nss_slot, parms->findLabel);
1846		if (publist == NULL) {
1847			rv = KMF_ERR_KEY_NOT_FOUND;
1848			goto cleanup;
1849		}
1850	} else if (parms->keyclass == KMF_ASYM_PRI) {
1851		prilist = PK11_ListPrivKeysInSlot(nss_slot,
1852			parms->findLabel, NULL);
1853		if (prilist == NULL) {
1854			rv = KMF_ERR_KEY_NOT_FOUND;
1855			goto cleanup;
1856		}
1857	} else if (parms->keyclass == KMF_SYMMETRIC) {
1858		symlist = PK11_ListFixedKeysInSlot(nss_slot, parms->findLabel,
1859		    NULL);
1860		if (symlist == NULL) {
1861			rv = KMF_ERR_KEY_NOT_FOUND;
1862			goto cleanup;
1863		}
1864	} else {
1865		rv = KMF_ERR_BAD_KEY_CLASS;
1866		goto cleanup;
1867	}
1868
1869	if (parms->keyclass == KMF_ASYM_PUB) {
1870		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1871			!PUBKEY_LIST_END(pubnode, publist) &&
1872			count < maxkeys;
1873			pubnode = PUBKEY_LIST_NEXT(pubnode), count++) {
1874			if (keys != NULL) {
1875				keys[count].kstype = KMF_KEYSTORE_NSS;
1876				keys[count].keyclass = KMF_ASYM_PUB;
1877				keys[count].keyp = (void *)pubnode->key;
1878				keys[count].keylabel =
1879					PK11_GetPublicKeyNickname(
1880						pubnode->key);
1881
1882				if (pubnode->key->keyType == rsaKey)
1883					keys[count].keyalg = KMF_RSA;
1884				else if (pubnode->key->keyType == dsaKey)
1885					keys[count].keyalg = KMF_DSA;
1886			}
1887		}
1888		*numkeys = count;
1889	} else if (parms->keyclass == KMF_ASYM_PRI) {
1890		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1891			!PRIVKEY_LIST_END(prinode, prilist) &&
1892			count < maxkeys;
1893			prinode = PRIVKEY_LIST_NEXT(prinode), count++) {
1894			if (keys != NULL) {
1895				keys[count].kstype = KMF_KEYSTORE_NSS;
1896				keys[count].keyclass = KMF_ASYM_PRI;
1897				keys[count].keyp = (void *)prinode->key;
1898				keys[count].keylabel =
1899					PK11_GetPrivateKeyNickname(
1900						prinode->key);
1901
1902				if (prinode->key->keyType == rsaKey)
1903					keys[count].keyalg = KMF_RSA;
1904				else if (prinode->key->keyType == dsaKey)
1905					keys[count].keyalg = KMF_DSA;
1906			}
1907		}
1908		*numkeys = count;
1909	} else if (parms->keyclass == KMF_SYMMETRIC) {
1910		count = 0;
1911		while (symlist && count < maxkeys) {
1912			PK11SymKey *symkey = symlist;
1913			CK_KEY_TYPE type;
1914			KMF_KEY_ALG keyalg;
1915
1916			type = PK11_GetSymKeyType(symkey);
1917			keyalg = pk11keytype2kmf(type);
1918
1919			/*
1920			 * If keytype is specified in the searching parameter,
1921			 * check the keytype and skip the key if its keytype
1922			 * doesn't match.
1923			 */
1924			symlist = PK11_GetNextSymKey(symkey);
1925			if (parms->keytype != KMF_KEYALG_NONE &&
1926			    parms->keytype != keyalg) {
1927				/* free that key since we aren't using it */
1928				PK11_FreeSymKey(symkey);
1929				continue;
1930			}
1931
1932			if (keys != NULL) {
1933				keys[count].kstype = KMF_KEYSTORE_NSS;
1934				keys[count].keyclass = KMF_SYMMETRIC;
1935				keys[count].keyp = (void *) symkey;
1936				keys[count].keylabel =
1937				    PK11_GetSymKeyNickname(symkey);
1938				keys[count].keyalg = keyalg;
1939			} else {
1940				PK11_FreeSymKey(symkey);
1941			}
1942			count++;
1943		}
1944		/*
1945		 * Cleanup memory for unused keys.
1946		 */
1947		while (symlist != NULL) {
1948			PK11SymKey *symkey = symlist;
1949			PK11_FreeSymKey(symkey);
1950			symlist = PK11_GetNextSymKey(symkey);
1951		}
1952	}
1953
1954	*numkeys = count;
1955cleanup:
1956	if (nss_slot != NULL) {
1957		PK11_FreeSlot(nss_slot);
1958	}
1959
1960	return (rv);
1961}
1962
1963static SECStatus
1964p12u_SwapUnicodeBytes(SECItem *uniItem)
1965{
1966	unsigned int i;
1967	unsigned char a;
1968	if ((uniItem == NULL) || (uniItem->len % 2)) {
1969		return (SECFailure);
1970		}
1971	for (i = 0; i < uniItem->len; i += 2) {
1972		a = uniItem->data[i];
1973		uniItem->data[i] = uniItem->data[i+1];
1974		uniItem->data[i+1] = a;
1975	}
1976	return (SECSuccess);
1977}
1978
1979static PRBool
1980p12u_ucs2_ascii_conversion_function(
1981	PRBool		toUnicode,
1982	unsigned char	*inBuf,
1983	unsigned int	inBufLen,
1984	unsigned char	*outBuf,
1985	unsigned int	maxOutBufLen,
1986	unsigned int	*outBufLen,
1987	PRBool		swapBytes)
1988{
1989	SECItem it = { 0 };
1990	SECItem *dup = NULL;
1991	PRBool ret;
1992
1993	it.data = inBuf;
1994	it.len = inBufLen;
1995	dup = SECITEM_DupItem(&it);
1996	/*
1997	 * If converting Unicode to ASCII, swap bytes before conversion
1998	 * as neccessary.
1999	 */
2000	if (!toUnicode && swapBytes) {
2001		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
2002			SECITEM_ZfreeItem(dup, PR_TRUE);
2003			return (PR_FALSE);
2004		}
2005	}
2006	/* Perform the conversion. */
2007	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
2008		outBuf, maxOutBufLen, outBufLen);
2009	if (dup)
2010		SECITEM_ZfreeItem(dup, PR_TRUE);
2011
2012	return (ret);
2013}
2014
2015static PRBool
2016p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
2017{
2018	if (!p12ctx || !p12ctx->filename) {
2019		return (PR_FALSE);
2020	}
2021
2022	if (fileRead) {
2023		p12ctx->file = PR_Open(p12ctx->filename,
2024			PR_RDONLY, 0400);
2025	} else {
2026		p12ctx->file = PR_Open(p12ctx->filename,
2027			PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
2028	}
2029
2030	if (!p12ctx->file) {
2031		p12ctx->error = PR_TRUE;
2032		return (PR_FALSE);
2033	}
2034
2035	return (PR_TRUE);
2036}
2037
2038static void
2039p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
2040{
2041	if (!ppCtx || !(*ppCtx)) {
2042		return;
2043	}
2044
2045	if ((*ppCtx)->file != NULL) {
2046		PR_Close((*ppCtx)->file);
2047	}
2048
2049	if ((*ppCtx)->filename != NULL) {
2050		if (removeFile) {
2051			PR_Delete((*ppCtx)->filename);
2052		}
2053		free((*ppCtx)->filename);
2054	}
2055
2056	free(*ppCtx);
2057	*ppCtx = NULL;
2058}
2059
2060static p12uContext *
2061p12u_InitContext(PRBool fileImport, char *filename)
2062{
2063	p12uContext *p12ctx;
2064
2065	p12ctx = PORT_ZNew(p12uContext);
2066	if (!p12ctx) {
2067		return (NULL);
2068	}
2069
2070	p12ctx->error = PR_FALSE;
2071	p12ctx->errorValue = 0;
2072	p12ctx->filename = strdup(filename);
2073
2074	if (!p12u_OpenFile(p12ctx, fileImport)) {
2075		p12u_DestroyContext(&p12ctx, PR_FALSE);
2076		return (NULL);
2077	}
2078
2079	return (p12ctx);
2080}
2081
2082static void
2083p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
2084{
2085	p12uContext *p12cxt = arg;
2086	int writeLen;
2087
2088	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
2089		return;
2090	}
2091
2092	if (p12cxt->file == NULL) {
2093		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2094		p12cxt->error = PR_TRUE;
2095		return;
2096	}
2097
2098	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
2099
2100	if (writeLen != (int)len) {
2101		PR_Close(p12cxt->file);
2102		free(p12cxt->filename);
2103		p12cxt->filename = NULL;
2104		p12cxt->file = NULL;
2105		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2106		p12cxt->error = PR_TRUE;
2107	}
2108}
2109
2110#define	HANDLE_NSS_ERROR(r) {\
2111	SET_ERROR(kmfh, PORT_GetError()); \
2112	rv = r; \
2113	goto out; }
2114
2115static KMF_RETURN
2116add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
2117	CERTCertificate *cert, SECItem *pwitem)
2118{
2119	KMF_RETURN rv = KMF_OK;
2120	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
2121
2122	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
2123	if (PK11_IsFIPS()) {
2124		certSafe = keySafe;
2125	} else {
2126		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
2127			SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
2128	}
2129
2130	if (!certSafe || !keySafe) {
2131		rv = KMF_ERR_INTERNAL;
2132		goto out;
2133	}
2134
2135	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
2136		CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
2137		SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
2138		!= SECSuccess) {
2139		rv = KMF_ERR_INTERNAL;
2140	}
2141out:
2142	return (rv);
2143}
2144
2145/*ARGSUSED*/
2146KMF_RETURN
2147NSS_ExportP12(KMF_HANDLE_T handle,
2148	KMF_EXPORTP12_PARAMS *params,
2149	int numcerts, KMF_X509_DER_CERT *certs,
2150	int numkeys, KMF_KEY_HANDLE *keylist,
2151	char *filename)
2152{
2153	KMF_RETURN rv;
2154	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
2155	SEC_PKCS12ExportContext *p12ecx = NULL;
2156	p12uContext *p12ctx = NULL;
2157	CERTCertList *certlist = NULL;
2158	CERTCertificate *nsscert = NULL;
2159	CERTCertListNode* node = NULL;
2160	PK11SlotInfo	*slot = NULL;
2161	SECItem pwitem = {NULL, 0};
2162
2163	rv = Do_NSS_Init(handle,
2164		params->nssparms, FALSE, &slot);
2165	if (rv != KMF_OK) {
2166		return (rv);
2167	}
2168
2169	rv = nss_authenticate(handle, slot, &params->cred);
2170	if (rv != KMF_OK) {
2171		return (rv);
2172	}
2173
2174	/*
2175	 * Find the certificate(s) first.
2176	 */
2177	if (params->certLabel) {
2178		nsscert = PK11_FindCertFromNickname(params->certLabel,
2179			NULL);
2180		if (nsscert == NULL) {
2181			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
2182		}
2183	} else {
2184		rv = nss_find_matching_certs(slot,
2185			params->issuer,
2186			params->subject,
2187			params->serial,
2188			&certlist, 0);
2189
2190		if (rv == KMF_OK && certlist == NULL) {
2191			return (KMF_ERR_CERT_NOT_FOUND);
2192		}
2193		if (rv != KMF_OK)
2194			return (rv);
2195	}
2196
2197	/*
2198	 * The KMF_CREDENTIAL holds the password to use for
2199	 * encrypting the PKCS12 key information.
2200	 */
2201	pwitem.data = (uchar_t *)params->p12cred.cred;
2202	pwitem.len = params->p12cred.credlen;
2203
2204	p12ctx = p12u_InitContext(PR_FALSE, filename);
2205	if (!p12ctx) {
2206		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2207	}
2208
2209	PORT_SetUCS2_ASCIIConversionFunction(
2210		p12u_ucs2_ascii_conversion_function);
2211
2212	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL,
2213		slot, NULL);
2214	if (!p12ecx) {
2215		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2216	}
2217
2218	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
2219		!= SECSuccess) {
2220		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
2221	}
2222
2223	/*
2224	 * NSS actually supports storing a list of keys and certs
2225	 * in the PKCS#12 PDU.  Nice feature.
2226	 */
2227	if (certlist != NULL) {
2228		for (node = CERT_LIST_HEAD(certlist);
2229			!CERT_LIST_END(node, certlist) && rv == KMF_OK;
2230			node = CERT_LIST_NEXT(node)) {
2231
2232			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
2233		}
2234	} else if (nsscert != NULL) {
2235		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
2236	}
2237
2238	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
2239		!= SECSuccess) {
2240		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
2241	}
2242out:
2243	if (nsscert)
2244		CERT_DestroyCertificate(nsscert);
2245
2246	if (certlist)
2247		CERT_DestroyCertList(certlist);
2248
2249	if (p12ctx)
2250		p12u_DestroyContext(&p12ctx, PR_FALSE);
2251
2252	if (p12ecx)
2253		SEC_PKCS12DestroyExportContext(p12ecx);
2254
2255	return (rv);
2256}
2257
2258#define	SETATTR(t, n, atype, value, size) \
2259	t[n].type = atype; \
2260	t[n].pValue = (CK_BYTE *)value; \
2261	t[n].ulValueLen = (CK_ULONG)size;
2262
2263KMF_RETURN
2264NSS_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2265	KMF_RAW_KEY_DATA *rawkey)
2266{
2267	KMF_RETURN rv = KMF_OK;
2268	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2269	SECStatus	ckrv = SECSuccess;
2270	PK11SlotInfo	*slot = NULL;
2271	CERTCertificate *nss_cert = NULL;
2272	SECKEYPrivateKeyInfo rpk;
2273	SECItem		nickname;
2274	KMF_DATA	derkey = { NULL, 0 };
2275	uchar_t		ver = 0;
2276
2277	if (!kmfh)
2278		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2279
2280	if (params == NULL || params->certificate == NULL || rawkey == NULL)
2281		return (KMF_ERR_BAD_PARAMETER);
2282
2283	rv = Do_NSS_Init(handle,
2284		params->nssparms, FALSE, &slot);
2285
2286	if (rv != KMF_OK)
2287		return (rv);
2288
2289	rv = nss_authenticate(handle, slot, &params->cred);
2290	if (rv != KMF_OK) {
2291		return (rv);
2292	}
2293
2294	/*
2295	 * Decode the cert into an NSS CERT object so we can access the
2296	 * SPKI and KeyUsage data later.
2297	 */
2298	nss_cert = CERT_DecodeCertFromPackage((char *)params->certificate->Data,
2299		params->certificate->Length);
2300
2301	if (nss_cert == NULL) {
2302		SET_ERROR(kmfh, PORT_GetError());
2303		rv = KMF_ERR_BAD_CERT_FORMAT;
2304		goto cleanup;
2305	}
2306
2307	(void) memset(&rpk, 0, sizeof (rpk));
2308
2309	rpk.arena = NULL;
2310	rpk.version.type = siUnsignedInteger;
2311	rpk.version.data = &ver;
2312	rpk.version.len = 1;
2313	if (rawkey->keytype == KMF_RSA) {
2314
2315		rv = DerEncodeRSAPrivateKey(&derkey, &rawkey->rawdata.rsa);
2316		if (rv != KMF_OK)
2317			goto cleanup;
2318
2319		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2320		rpk.privateKey.data = derkey.Data;
2321		rpk.privateKey.len = derkey.Length;
2322		rpk.attributes = NULL;
2323
2324
2325	} else if (rawkey->keytype == KMF_DSA) {
2326		rv = DerEncodeDSAPrivateKey(&derkey, &rawkey->rawdata.dsa);
2327		if (rv != KMF_OK)
2328			goto cleanup;
2329
2330		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2331		rpk.privateKey.data = derkey.Data;
2332		rpk.privateKey.len = derkey.Length;
2333		rpk.attributes = NULL;
2334
2335	} else {
2336		return (KMF_ERR_BAD_PARAMETER);
2337	}
2338
2339	nickname.data = (uchar_t *)params->label;
2340	nickname.len = (params->label ? strlen(params->label) : 0);
2341
2342	ckrv = PK11_ImportPrivateKeyInfo(slot, &rpk,
2343		&nickname, &nss_cert->subjectPublicKeyInfo.subjectPublicKey,
2344		TRUE, TRUE, nss_cert->keyUsage, NULL);
2345
2346	if (ckrv != CKR_OK) {
2347		SET_ERROR(kmfh, PORT_GetError());
2348		rv = KMF_ERR_INTERNAL;
2349	}
2350
2351cleanup:
2352	if (nss_cert != NULL) {
2353		CERT_DestroyCertificate(nss_cert);
2354	}
2355	KMF_FreeData(&derkey);
2356	return (rv);
2357}
2358
2359KMF_RETURN
2360NSS_CreateSymKey(KMF_HANDLE_T handle,
2361	KMF_CREATESYMKEY_PARAMS *params,
2362	KMF_KEY_HANDLE *symkey)
2363{
2364	KMF_RETURN rv = KMF_OK;
2365	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2366	PK11SlotInfo *nss_slot = NULL;
2367	PK11SymKey *nsskey = NULL;
2368	CK_MECHANISM_TYPE keyType;
2369	SECStatus nssrv;
2370	int keySize;
2371
2372	if (params == NULL || symkey == NULL) {
2373		return (KMF_ERR_BAD_PARAMETER);
2374	}
2375
2376	switch (params->keytype) {
2377	case KMF_AES:
2378		keyType = CKM_AES_KEY_GEN;
2379		keySize = params->keylength;
2380		if (keySize == 0 || (keySize % 8) != 0)
2381			return (KMF_ERR_BAD_KEY_SIZE);
2382		break;
2383	case KMF_RC4:
2384		keyType = CKM_RC4_KEY_GEN;
2385		keySize = params->keylength;
2386		if (keySize == 0 || (keySize % 8) != 0)
2387			return (KMF_ERR_BAD_KEY_SIZE);
2388		break;
2389	case KMF_DES:
2390		keyType = CKM_DES_KEY_GEN;
2391		keySize = 0; /* required by PK11_TokenKeyGen()  */
2392		break;
2393	case KMF_DES3:
2394		keyType = CKM_DES3_KEY_GEN;
2395		keySize = 0; /* required by PK11_TokenKeyGen() */
2396		break;
2397	case KMF_GENERIC_SECRET:
2398		keyType = CKM_GENERIC_SECRET_KEY_GEN;
2399		keySize = params->keylength;
2400		if (keySize == 0 || (keySize % 8) != 0)
2401			return (KMF_ERR_BAD_KEY_SIZE);
2402		break;
2403	default:
2404		rv = KMF_ERR_BAD_KEY_TYPE;
2405		goto out;
2406	}
2407
2408	rv = Do_NSS_Init(handle,
2409		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
2410	if (rv != KMF_OK) {
2411		return (rv);
2412	}
2413
2414	rv = nss_authenticate(handle, nss_slot, &params->cred);
2415	if (rv != KMF_OK) {
2416		return (rv);
2417	}
2418
2419	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize,  NULL,
2420	    PR_TRUE, (void *)params->cred.cred);
2421	if (nsskey == NULL) {
2422		SET_ERROR(kmfh, PORT_GetError());
2423		rv = KMF_ERR_KEYGEN_FAILED;
2424		goto out;
2425	}
2426
2427	nssrv = PK11_SetSymKeyNickname(nsskey, params->keylabel);
2428	if (nssrv != SECSuccess) {
2429		SET_ERROR(kmfh, PORT_GetError());
2430		rv = KMF_ERR_KEYGEN_FAILED;
2431		goto out;
2432	}
2433
2434	symkey->kstype = KMF_KEYSTORE_NSS;
2435	symkey->keyalg = params->keytype;
2436	symkey->keyclass = KMF_SYMMETRIC;
2437	symkey->israw = FALSE;
2438	symkey->keyp = (void *)nsskey;
2439
2440out:
2441	if (nss_slot != NULL)
2442		PK11_FreeSlot(nss_slot);
2443
2444	if (rv != KMF_OK && nsskey != NULL) {
2445		PK11_DeleteTokenSymKey(nsskey);
2446		PK11_FreeSymKey(nsskey);
2447	}
2448	return (rv);
2449}
2450
2451KMF_RETURN
2452NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2453	KMF_RAW_SYM_KEY *rkey)
2454{
2455	KMF_RETURN rv = KMF_OK;
2456	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2457	SECItem *value = NULL;
2458	PK11SymKey *nsskey;
2459	SECStatus nss_rv;
2460
2461	if (kmfh == NULL)
2462		return (KMF_ERR_UNINITIALIZED);
2463
2464	if (symkey == NULL || rkey == NULL)
2465		return (KMF_ERR_BAD_PARAMETER);
2466	else if (symkey->keyclass != KMF_SYMMETRIC)
2467		return (KMF_ERR_BAD_KEY_CLASS);
2468
2469	if (symkey->israw) {
2470		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2471
2472		if (rawkey == NULL ||
2473		    rawkey->rawdata.sym.keydata.val == NULL ||
2474		    rawkey->rawdata.sym.keydata.len == 0)
2475			return (KMF_ERR_BAD_KEYHANDLE);
2476
2477		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2478		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2479			return (KMF_ERR_MEMORY);
2480		(void) memcpy(rkey->keydata.val,
2481			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2482	} else {
2483		nsskey = (PK11SymKey *)(symkey->keyp);
2484		if (nsskey == NULL)
2485			return (KMF_ERR_BAD_KEYHANDLE);
2486
2487		nss_rv = PK11_ExtractKeyValue(nsskey);
2488		if (nss_rv != SECSuccess) {
2489			SET_ERROR(kmfh, PORT_GetError());
2490			rv = KMF_ERR_GETKEYVALUE_FAILED;
2491			goto out;
2492		}
2493
2494		value = PK11_GetKeyData(nsskey);
2495		if (value == NULL) {
2496			SET_ERROR(kmfh, PORT_GetError());
2497			rv = KMF_ERR_GETKEYVALUE_FAILED;
2498			goto out;
2499		}
2500
2501		if (value->len == 0 || value->data == NULL) {
2502			rv = KMF_ERR_GETKEYVALUE_FAILED;
2503			goto out;
2504		}
2505
2506		rkey->keydata.val = malloc(value->len);
2507		if (rkey->keydata.val == NULL) {
2508			rv = KMF_ERR_MEMORY;
2509			goto out;
2510		}
2511		(void) memcpy(rkey->keydata.val, value->data, value->len);
2512		rkey->keydata.len = value->len;
2513		(void) memset(value->data, 0, value->len);
2514	}
2515out:
2516	if (value != NULL)
2517		SECITEM_FreeItem(value, PR_TRUE);
2518	return (rv);
2519}
2520
2521KMF_RETURN
2522NSS_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2523	KMF_CREDENTIAL *newpin)
2524{
2525	KMF_RETURN ret = KMF_OK;
2526	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2527	int rv;
2528	PK11SlotInfo *nss_slot = NULL;
2529
2530	if (handle == NULL || params == NULL || newpin == NULL) {
2531		return (KMF_ERR_BAD_PARAMETER);
2532	}
2533
2534	ret = Do_NSS_Init(handle,
2535		params->ks_opt_u.nss_opts,
2536		FALSE, &nss_slot);
2537	/* If it was uninitialized, set it */
2538	if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2539		rv = PK11_InitPin(nss_slot, NULL, newpin->cred);
2540		if (rv != SECSuccess) {
2541			SET_ERROR(kmfh, PORT_GetError());
2542			ret = KMF_ERR_AUTH_FAILED;
2543		} else {
2544			ret = KMF_OK;
2545		}
2546	} else if (ret == KMF_OK) {
2547		ret = nss_authenticate(handle, nss_slot, &params->cred);
2548		if (ret != KMF_OK) {
2549			return (ret);
2550		}
2551		rv = PK11_ChangePW(nss_slot,
2552			params->cred.cred, newpin->cred);
2553		if (rv != SECSuccess) {
2554			SET_ERROR(kmfh, PORT_GetError());
2555			ret = KMF_ERR_AUTH_FAILED;
2556		}
2557	}
2558
2559	return (ret);
2560}
2561