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