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