xref: /illumos-gate/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c (revision b6805bf78d2bbbeeaea8909a05623587b42d58b3)
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 
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 	NSS_StoreKey,
158 	NULL /* Finalize */
159 };
160 
161 /* additions for importing and exporting PKCS 12 files */
162 typedef 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 
172 KMF_PLUGIN_FUNCLIST *
173 KMF_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 
186 static char *
187 /*ARGSUSED*/
188 nss_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 
198 static KMF_RETURN
199 nss_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 
228 static SECStatus
229 Init_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++;
252 end:
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  */
262 KMF_RETURN
263 NSS_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  */
304 KMF_RETURN
305 do_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 
345 end:
346 	return (rv);
347 }
348 
349 static KMF_RETURN
350 nss2kmf_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 
370 static KMF_RETURN
371 nss_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 
428 static KMF_RETURN
429 nss_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 			}
527 skip:
528 			node = CERT_LIST_NEXT(node);
529 			continue;
530 delete_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 
545 static KMF_RETURN
546 convertCertList(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 
584 KMF_RETURN
585 NSS_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 
667 void
668 /*ARGSUSED*/
669 NSS_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 
685 KMF_RETURN
686 NSS_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 	}
774 out:
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 
786 static void
787 InitRandom(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 
805 KMF_RETURN
806 NSS_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 	}
987 cleanup:
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 
1013 KMF_RETURN
1014 NSS_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 
1085 KMF_RETURN
1086 NSS_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 
1125 KMF_RETURN
1126 NSS_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 
1206 KMF_RETURN
1207 NSS_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 
1227 KMF_RETURN
1228 NSS_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 
1290 KMF_RETURN
1291 NSS_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 
1338 static KMF_KEY_ALG
1339 pk11keytype2kmf(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 
1362 KMF_RETURN
1363 NSS_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 
1577 cleanup:
1578 	if (nss_slot != NULL) {
1579 		PK11_FreeSlot(nss_slot);
1580 	}
1581 
1582 	return (rv);
1583 }
1584 
1585 static SECStatus
1586 p12u_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 
1601 static PRBool
1602 p12u_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 
1637 static PRBool
1638 p12u_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 
1659 static void
1660 p12u_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 
1681 static p12uContext *
1682 p12u_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 
1703 static void
1704 p12u_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 
1736 static KMF_RETURN
1737 add_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 	}
1762 out:
1763 	return (rv);
1764 }
1765 
1766 KMF_RETURN
1767 NSS_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 	}
1879 out:
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 
1900 KMF_RETURN
1901 NSS_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 
2013 out:
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 
2024 KMF_RETURN
2025 NSS_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 	}
2088 out:
2089 	if (value != NULL)
2090 		SECITEM_FreeItem(value, PR_TRUE);
2091 	return (rv);
2092 }
2093 
2094 KMF_RETURN
2095 NSS_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 
2140 KMF_RETURN
2141 NSS_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 
2274 cleanup:
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  */
2285 static KMF_RETURN
2286 store_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 
2339 out:
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 
2352 KMF_RETURN
2353 NSS_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 
2382 out:
2383 	if (nss_slot != NULL) {
2384 		PK11_FreeSlot(nss_slot);
2385 	}
2386 
2387 	return (ret);
2388 }
2389 
2390 
2391 KMF_RETURN
2392 NSS_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 
2448 cleanup:
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 
2459 KMF_RETURN
2460 NSS_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 
2541 out:
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 
2561 KMF_RETURN
2562 NSS_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 
2697 out:
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 
2721 KMF_RETURN
2722 NSS_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 
2818 out:
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 
2841 KMF_RETURN
2842 NSS_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 
2920 out:
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